From 9202da6fac5c9f818ba8c70f3902cc03f6bc1d16 Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Tue, 12 May 2020 20:18:47 +0200 Subject: Allow to set feature permission before first ever navigation Since PermissionManagerQt functions independent of webcontents initialization, permission installment may be done earlier (right after page base constructor). Practically, this allows to grant/deny permission before first ever navigation to avoid permission feature request from well-behaving web application. Unfortunately, this only applies to Web Notifications: there is a way to check without request: Notification.permission javascript static object. Other supported features lack similar mechanism: they operate through success/failure callbacks, which unconditionally invoke permission requests, and Page/View API doesn't automatically answer with remembered permissions. Task-number: QTBUG-83476 Change-Id: I63a3cbca25498d5026975073e125f2ab4f9ab2ad Reviewed-by: Allan Sandfeld Jensen --- .../widgets/qwebenginepage/tst_qwebenginepage.cpp | 66 ++++++++++++++-------- 1 file changed, 42 insertions(+), 24 deletions(-) (limited to 'tests/auto') diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 3f3534931..515aa4ebb 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -203,11 +203,10 @@ private Q_SLOTS: void triggerActionWithoutMenu(); void dynamicFrame(); - void notificationRequest_data(); - void notificationRequest(); + void notificationPermission_data(); + void notificationPermission(); void sendNotification(); void contentsSize(); - void notificationPermission(); void setLifecycleState(); void setVisible(); @@ -3590,42 +3589,61 @@ public: } }; -void tst_QWebEnginePage::notificationRequest_data() +void tst_QWebEnginePage::notificationPermission_data() { + QTest::addColumn("setOnInit"); QTest::addColumn("policy"); QTest::addColumn("permission"); - QTest::newRow("deny") << QWebEnginePage::PermissionDeniedByUser << "denied"; - QTest::newRow("grant") << QWebEnginePage::PermissionGrantedByUser << "granted"; + QTest::newRow("denyOnInit") << true << QWebEnginePage::PermissionDeniedByUser << "denied"; + QTest::newRow("deny") << false << QWebEnginePage::PermissionDeniedByUser << "denied"; + QTest::newRow("grant") << false << QWebEnginePage::PermissionGrantedByUser << "granted"; + QTest::newRow("grantOnInit") << true << QWebEnginePage::PermissionGrantedByUser << "granted"; } -void tst_QWebEnginePage::notificationRequest() +void tst_QWebEnginePage::notificationPermission() { + QFETCH(bool, setOnInit); QFETCH(QWebEnginePage::PermissionPolicy, policy); QFETCH(QString, permission); - NotificationPage page(policy); - QVERIFY(page.spyLoad.waitForResult()); + QWebEngineProfile otr; + QWebEnginePage page(&otr, nullptr); - page.resetPermission(); - QCOMPARE(page.getPermission(), "default"); + QUrl baseUrl("https://www.example.com/somepage.html"); - page.requestPermission(); - page.spyRequest.waitForResult(); - QVERIFY(page.spyRequest.wasCalled()); + bool permissionRequested = false, errorState = false; + connect(&page, &QWebEnginePage::featurePermissionRequested, &page, [&] (const QUrl &o, QWebEnginePage::Feature f) { + if (f != QWebEnginePage::Notifications) + return; + if (permissionRequested || o != baseUrl.url(QUrl::RemoveFilename)) { + qWarning() << "Unexpected case. Can't proceed." << setOnInit << permissionRequested << o; + errorState = true; + return; + } + permissionRequested = true; + page.setFeaturePermission(o, f, policy); + }); - QCOMPARE(page.getPermission(), permission); -} + if (setOnInit) + page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, policy); -void tst_QWebEnginePage::notificationPermission() -{ - QWebEngineProfile otr; - QWebEnginePage page(&otr, nullptr); QSignalSpy spy(&page, &QWebEnginePage::loadFinished); - page.setHtml(QString("Test"), QUrl("https://www.example.com")); + page.setHtml(QString("Test"), baseUrl); QTRY_COMPARE(spy.count(), 1); - QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), QLatin1String("default")); - page.setFeaturePermission(QUrl("https://www.example.com"), QWebEnginePage::Notifications, QWebEnginePage::PermissionGrantedByUser); - QTRY_COMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), QLatin1String("granted")); + + QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), setOnInit ? permission : QLatin1String("default")); + + if (!setOnInit) { + page.setFeaturePermission(baseUrl, QWebEnginePage::Notifications, policy); + QTRY_COMPARE(evaluateJavaScriptSync(&page, QStringLiteral("Notification.permission")), permission); + } + + auto js = QStringLiteral("var permission; Notification.requestPermission().then(p => { permission = p })"); + evaluateJavaScriptSync(&page, js); + QTRY_COMPARE(evaluateJavaScriptSync(&page, "permission").toString(), permission); + // permission is not 'remembered' from api standpoint, hence is not suppressed on explicit call from JS + QVERIFY(permissionRequested); + QVERIFY(!errorState); } void tst_QWebEnginePage::sendNotification() -- cgit v1.2.3 From 7b6d15cdf271772695d28bf48f1f41a29dc29e28 Mon Sep 17 00:00:00 2001 From: Tamas Zakor Date: Tue, 5 May 2020 12:25:58 +0200 Subject: Fix path validation in FilePickerController::accepted() In some cases QUrl::toLocalFile() does wrong path conversion on Windows. Therefore we have to convert the file URL to absolute path in another way and use FilePath::IsAbsolute() for validating that. Also stabilize WebEngineViewSingleFileUpload tests. They didn't wait for html title change when the expected value was the same as the default title. Change-Id: Ica7798a299f9b28657afeeccccfba3fdecc515e2 Reviewed-by: Allan Sandfeld Jensen --- tests/auto/quick/qmltests2/data/tst_filePicker.qml | 40 +++++++++++++++------- 1 file changed, 28 insertions(+), 12 deletions(-) (limited to 'tests/auto') diff --git a/tests/auto/quick/qmltests2/data/tst_filePicker.qml b/tests/auto/quick/qmltests2/data/tst_filePicker.qml index ffd7ef87b..ab30d9e82 100644 --- a/tests/auto/quick/qmltests2/data/tst_filePicker.qml +++ b/tests/auto/quick/qmltests2/data/tst_filePicker.qml @@ -36,6 +36,7 @@ TestWebEngineView { id: webEngineView width: 400 height: 300 + property var titleChanges: [] function driveLetter() { if (Qt.platform.os !== "windows") @@ -54,6 +55,8 @@ TestWebEngineView { signalName: "renderProcessTerminated" } + onTitleChanged: { titleChanges.push(webEngineView.title) } + TestCase { name: "WebEngineViewSingleFileUpload" when: windowShown @@ -65,6 +68,7 @@ TestWebEngineView { FilePickerParams.nameFilters = [] titleSpy.clear() terminationSpy.clear() + titleChanges = [] } function cleanup() { @@ -80,14 +84,14 @@ TestWebEngineView { function test_acceptSingleFileSelection_data() { return [ + { tag: "test.txt", input: "test.txt", expected: "Failed to Upload" }, { tag: driveLetter() + "/test.txt", input: driveLetter() + "/test.txt", expected: "test.txt" }, - { tag: driveLetter() + "test.txt", input: driveLetter() + "test.txt", expected: "Failed to Upload" }, { tag: driveLetter() + "/tést.txt", input: driveLetter() + "/tést.txt", expected: "tést.txt" }, { tag: driveLetter() + "/t%65st.txt", input: driveLetter() + "/t%65st.txt", expected: "t%65st.txt" }, { tag: "file:///" + driveLetter() + "test.txt", input: "file:///" + driveLetter() + "test.txt", expected: "test.txt" }, { tag: "file:///" + driveLetter() + "tést.txt", input: "file:///" + driveLetter() + "tést.txt", expected: "tést.txt" }, - { tag: "file:///" + driveLetter() + "t%65st.txt", input: "file:///" + driveLetter() + "t%65st.txt", expected: "test.txt" }, - { tag: "file://" + driveLetter() + "test.txt", input: "file://" + driveLetter() + "test.txt", expected: "test.txt" }, + { tag: "file:///" + driveLetter() + "t%65st.txt", input: "file:///" + driveLetter() + "t%65st.txt", expected: "t%65st.txt" }, + { tag: "file://" + driveLetter() + "test.txt", input: "file://" + driveLetter() + "test.txt", expected: "Failed to Upload" }, { tag: "file:/" + driveLetter() + "test.txt", input: "file:/" + driveLetter() + "test.txt", expected: "test.txt"}, { tag: "file:test//test.txt", input: "file:test//test.txt", expected: "Failed to Upload" }, { tag: "http://test.txt", input: "http://test.txt", expected: "Failed to Upload" }, @@ -107,7 +111,10 @@ TestWebEngineView { keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. tryCompare(FilePickerParams, "filePickerOpened", true); - tryCompare(webEngineView, "title", row.expected); + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(webEngineView, "title", "about:blank"); + compare(titleChanges[titleChanges.length-2], row.expected); // Custom dialog @@ -125,7 +132,10 @@ TestWebEngineView { keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. tryVerify(function() { return finished; }); - tryCompare(webEngineView, "title", row.expected); + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(webEngineView, "title", "about:blank"); + compare(titleChanges[titleChanges.length-2], row.expected); webEngineView.fileDialogRequested.disconnect(acceptedFileHandler); } @@ -212,19 +222,19 @@ TestWebEngineView { { tag: "C:/test.txt", input: "C:/test.txt", expected: "test.txt"}, { tag: "C:\\test.txt", input: "C:\\test.txt", expected: "test.txt"}, { tag: "C:\\Documents and Settings\\test\\test.txt", input: "C:\\Documents and Settings\\test\\test.txt", expected: "test.txt"}, - { tag: "\\\\applib\\products\\a%2Db\\ abc%5F9\\t.est\\test.txt", input: "file://applib/products/a%2Db/ abc%5F9/4148.920a/media/test.txt", expected: "test.txt"}, - { tag: "file://applib/products/a%2Db/ abc%5F9/t.est/test.txt", input: "file://applib/products/a%2Db/ abc%5F9/4148.920a/media/test.txt", expected: "test.txt"}, + { tag: "\\\\applib\\products\\a%2Db\\ abc%5F9\\t.est\\test.txt", input: "\\\\applib\\products\\a%2Db\\ abc%5F9\\t.est\\test.txt", expected: "test.txt"}, + { tag: "file://applib/products/a%2Db/ abc%5F9/4148.920a/media/test.txt", input: "file://applib/products/a%2Db/ abc%5F9/4148.920a/media/test.txt", expected: "test.txt"}, { tag: "file://applib/products/a-b/abc_1/t.est/test.txt", input: "file://applib/products/a-b/abc_1/t.est/test.txt", expected: "test.txt"}, { tag: "file:\\\\applib\\products\\a-b\\abc_1\\t:est\\test.txt", input: "file:\\\\applib\\products\\a-b\\abc_1\\t:est\\test.txt", expected: "test.txt"}, - { tag: "file:C:/test.txt", input: "file:C:/test.txt", expected: "Failed to Upload"}, - { tag: "file:/C:/test.txt", input: "file:/C:/test.txt", expected: "Failed to Upload"}, + { tag: "file:C:/test.txt", input: "file:C:/test.txt", expected: "test.tx"}, + { tag: "file:/C:/test.txt", input: "file:/C:/test.txt", expected: "test.tx"}, { tag: "file://C:/test.txt", input: "file://C:/test.txt", expected: "Failed to Upload"}, { tag: "file:///C:test.txt", input: "file:///C:test.txt", expected: "Failed to Upload"}, { tag: "file:///C:/test.txt", input: "file:///C:/test.txt", expected: "test.txt"}, { tag: "file:///C:\\test.txt", input: "file:///C:\\test.txt", expected: "test.txt"}, { tag: "file:\\//C:/test.txt", input: "file:\\//C:/test.txt", expected: "test.txt"}, { tag: "file:\\\\/C:\\test.txt", input: "file:\\\\/C:\\test.txt", expected: "test.txt"}, - { tag: "\\\\?\\C:/test.txt", input: "\\\\?\\C:/test.txt", expected: "Failed to Upload"}, + { tag: "\\\\?\\C:/test.txt", input: "\\\\?\\C:/test.txt", expected: "test.tx"}, ]; } @@ -241,7 +251,10 @@ TestWebEngineView { keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. tryCompare(FilePickerParams, "filePickerOpened", true); - tryCompare(webEngineView, "title", row.expected); + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(webEngineView, "title", "about:blank"); + compare(titleChanges[titleChanges.length-2], row.expected); // Custom dialog @@ -259,7 +272,10 @@ TestWebEngineView { keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog. tryVerify(function() { return finished; }); - tryCompare(webEngineView, "title", row.expected); + webEngineView.url = Qt.resolvedUrl("about:blank"); + verify(webEngineView.waitForLoadSucceeded()); + tryCompare(webEngineView, "title", "about:blank"); + compare(titleChanges[titleChanges.length-2], row.expected); webEngineView.fileDialogRequested.disconnect(acceptedFileHandler); } -- cgit v1.2.3 From 17cac776b2ec30af8f928d648f4708f8e1a25b5e Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 21 May 2020 16:28:02 +0200 Subject: Fix crash on WebContentsDelegateQt::CloseContents() CloseContents() triggers a windowCloseRequested() signal. The handler of the signal might close the QWebEngineView and it would result the destruction of the WebContentsDelegateQt. Thus, any operation on WebContentsDelegateQt is not safe after a WebContentsAdapterClient::close() call. For example, calling QWebEngineView::close() on QWebEnginePage::windowCloseRequested() would result crash because it sets life cycle state to discarded which destructs web contents. Fixes: QTBUG-84355 Change-Id: I5da404bc9b1923cc19085ee899b550da49d1416b Reviewed-by: Allan Sandfeld Jensen --- .../widgets/qwebenginepage/tst_qwebenginepage.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'tests/auto') diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 515aa4ebb..e4e451a55 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -231,6 +231,7 @@ private Q_SLOTS: void renderProcessPid(); void backgroundColor(); void audioMuted(); + void closeContents(); private: static QPoint elementCenter(QWebEnginePage *page, const QString &id); @@ -4641,6 +4642,27 @@ void tst_QWebEnginePage::audioMuted() QCOMPARE(spy[1][0], QVariant(false)); } +void tst_QWebEnginePage::closeContents() +{ + TestPage page; + QSignalSpy windowCreatedSpy(&page, &TestPage::windowCreated); + page.runJavaScript("var dialog = window.open('', '', 'width=100, height=100');"); + QTRY_COMPARE(windowCreatedSpy.count(), 1); + + QWebEngineView *dialogView = new QWebEngineView; + QWebEnginePage *dialogPage = page.createdWindows[0]; + dialogPage->setView(dialogView); + QCOMPARE(dialogPage->lifecycleState(), QWebEnginePage::LifecycleState::Active); + + // This should not crash. + connect(dialogPage, &QWebEnginePage::windowCloseRequested, dialogView, &QWebEngineView::close); + page.runJavaScript("dialog.close();"); + + // QWebEngineView::closeEvent() sets the life cycle state to discarded. + QTRY_COMPARE(dialogPage->lifecycleState(), QWebEnginePage::LifecycleState::Discarded); + delete dialogView; +} + static QByteArrayList params = {QByteArrayLiteral("--use-fake-device-for-media-stream")}; W_QTEST_MAIN(tst_QWebEnginePage, params) -- cgit v1.2.3 From e63d27ca775429df8c3f03dc2df001e502119db1 Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Wed, 20 May 2020 08:55:43 +0200 Subject: Remove leftover of tst_QWebEnginePage::inputFieldFocus auto test The test has been removed by: cfef4615 Delete QtWebKit tests from tst_qwebenginepage.cpp Pick-to: 5.15 Change-Id: I677772f00c99ae3b6e33a2d61c7135d4306d3674 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 0891ac9c05b96471a0858011ef4f84b353337d16) --- tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'tests/auto') diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index e4e451a55..0368e7af5 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -81,8 +81,6 @@ public: tst_QWebEnginePage(); virtual ~tst_QWebEnginePage(); - bool eventFilter(QObject *watched, QEvent *event); - public Q_SLOTS: void init(); void cleanup(); @@ -241,8 +239,6 @@ private: QWebEngineView* m_view; QWebEnginePage* m_page; - QWebEngineView* m_inputFieldsTestView; - int m_inputFieldTestPaintCount; QString tmpDirPath() const { static QString tmpd = QDir::tempPath() + "/tst_qwebenginepage-" @@ -259,16 +255,6 @@ tst_QWebEnginePage::~tst_QWebEnginePage() { } -bool tst_QWebEnginePage::eventFilter(QObject* watched, QEvent* event) -{ - // used on the inputFieldFocus test - if (watched == m_inputFieldsTestView) { - if (event->type() == QEvent::Paint) - m_inputFieldTestPaintCount++; - } - return QObject::eventFilter(watched, event); -} - void tst_QWebEnginePage::init() { m_view = new QWebEngineView(); -- cgit v1.2.3 From f3b0a9b8563e2ff6298db219b782992a52d6f9ab Mon Sep 17 00:00:00 2001 From: Tamas Zakor Date: Fri, 8 May 2020 07:49:35 +0200 Subject: Add test for first party urls of service worker Change-Id: Ic26d982ef9695705a9f7c757b7d983824b31a070 Reviewed-by: Allan Sandfeld Jensen --- .../resources/sw.html | 16 ++++ .../resources/sw.js | 3 + .../tst_qwebengineurlrequestinterceptor.cpp | 88 ++++++++++++++++++++++ .../tst_qwebengineurlrequestinterceptor.qrc | 2 + 4 files changed, 109 insertions(+) create mode 100644 tests/auto/core/qwebengineurlrequestinterceptor/resources/sw.html create mode 100644 tests/auto/core/qwebengineurlrequestinterceptor/resources/sw.js (limited to 'tests/auto') diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/sw.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/sw.html new file mode 100644 index 000000000..af44b45a2 --- /dev/null +++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/sw.html @@ -0,0 +1,16 @@ + + + + + + diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/sw.js b/tests/auto/core/qwebengineurlrequestinterceptor/resources/sw.js new file mode 100644 index 000000000..2216e2a07 --- /dev/null +++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/sw.js @@ -0,0 +1,3 @@ +self.addEventListener('install', function(event) { + console.log('ServiceWorker installed'); +}); diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index b8ecce635..350c15174 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -74,6 +74,8 @@ private Q_SLOTS: void passRefererHeader(); void initiator_data(); void initiator(); + void jsServiceWorker_data(); + void jsServiceWorker(); }; tst_QWebEngineUrlRequestInterceptor::tst_QWebEngineUrlRequestInterceptor() @@ -186,6 +188,58 @@ public: } }; +class TestServer : public HttpServer +{ +public: + TestServer() + { + connect(this, &HttpServer::newRequest, this, &TestServer::onNewRequest); + } + +private: + void onNewRequest(HttpReqRep *rr) + { + const QDir resourceDir(TESTS_SOURCE_DIR "qwebengineurlrequestinterceptor/resources"); + QString path = rr->requestPath(); + path.remove(0, 1); + + if (rr->requestMethod() != "GET" || !resourceDir.exists(path)) + { + rr->setResponseStatus(404); + rr->sendResponse(); + return; + } + + QFile file(resourceDir.filePath(path)); + file.open(QIODevice::ReadOnly); + QByteArray data = file.readAll(); + rr->setResponseBody(data); + QMimeDatabase db; + QMimeType mime = db.mimeTypeForFileNameAndData(file.fileName(), data); + rr->setResponseHeader(QByteArrayLiteral("content-type"), mime.name().toUtf8()); + rr->sendResponse(); + } +}; + +class ConsolePage : public QWebEnginePage { + Q_OBJECT +public: + ConsolePage(QWebEngineProfile* profile) : QWebEnginePage(profile) {} + + virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) + { + levels.append(level); + messages.append(message); + lineNumbers.append(lineNumber); + sourceIDs.append(sourceID); + } + + QList levels; + QStringList messages; + QList lineNumbers; + QStringList sourceIDs; +}; + void tst_QWebEngineUrlRequestInterceptor::interceptRequest_data() { QTest::addColumn("setter"); @@ -699,5 +753,39 @@ void tst_QWebEngineUrlRequestInterceptor::initiator() QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); } +void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker_data() +{ + interceptRequest_data(); +} + +void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker() +{ + QFETCH(InterceptorSetter, setter); + + TestServer server; + QVERIFY(server.start()); + + QWebEngineProfile profile(QStringLiteral("Test")); + std::unique_ptr page; + page.reset(new ConsolePage(&profile)); + TestRequestInterceptor interceptor(/* intercept */ false); + (profile.*setter)(&interceptor); + QVERIFY(loadSync(page.get(), server.url("/sw.html"))); + + // We expect only one message here, because logging of services workers is not exposed in our API. + QTRY_COMPARE(page->messages.count(), 1); + QCOMPARE(page->levels.at(0), QWebEnginePage::InfoMessageLevel); + + QUrl firstPartyUrl = QUrl(server.url().toString() + "sw.js"); + QList infos; + // Service Worker + QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker)); + infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker); + foreach (auto info, infos) + QCOMPARE(info.firstPartyUrl, firstPartyUrl); + + QVERIFY(server.stop()); +} + QTEST_MAIN(tst_QWebEngineUrlRequestInterceptor) #include "tst_qwebengineurlrequestinterceptor.moc" diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc index 13dbb134e..6a34635f7 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc @@ -17,6 +17,8 @@ resources/resource_in_iframe.html resources/script.js resources/style.css + resources/sw.html + resources/sw.js resources/icons/favicon.png -- cgit v1.2.3 From 84a4324fd3b947b7464b5ea04453da2a7a25730e Mon Sep 17 00:00:00 2001 From: Kirill Burtsev Date: Wed, 14 Aug 2019 19:15:37 +0200 Subject: QML test case for certificate error handling Change-Id: I5609440666d41ea273f3be44fd860195750af4dd Reviewed-by: Allan Sandfeld Jensen --- .../auto/quick/qmltests/data/TestWebEngineView.qml | 7 ++ .../quick/qmltests/data/tst_certificateError.qml | 114 +++++++++++++++++++++ tests/auto/quick/qmltests/qmltests.pro | 1 + tests/auto/quick/qmltests/tst_qmltests.cpp | 4 + tests/auto/shared/httpreqrep.h | 4 +- 5 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 tests/auto/quick/qmltests/data/tst_certificateError.qml (limited to 'tests/auto') diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml index f5e83c5d2..6db076ae8 100644 --- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml +++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml @@ -111,5 +111,12 @@ WebEngineView { onWindowCloseRequested: { windowCloseRequestedSignalEmitted = true; } + + function getBodyText() { + let text + runJavaScript('document.body.innerText', function(t) { text = t }) + testCase.tryVerify(function() { return text !== undefined }) + return text + } } diff --git a/tests/auto/quick/qmltests/data/tst_certificateError.qml b/tests/auto/quick/qmltests/data/tst_certificateError.qml new file mode 100644 index 000000000..0629be175 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_certificateError.qml @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 +import QtWebEngine 1.9 + +import Test.Shared 1.0 as Shared + +TestWebEngineView { + id: view; width: 320; height: 320 + + property bool deferError: false + property bool acceptCertificate: false + + onCertificateError: function(error) { + if (deferError) + error.defer() + else if (acceptCertificate) + error.ignoreCertificateError() + else + error.rejectCertificate() + } + + SignalSpy { + id: spyError + target: view + signalName: 'certificateError' + } + + TestCase { + name: 'CertificateError' + when: windowShown + + function initTestCase() { + Shared.HttpsServer.setExpectError(true) + Shared.HttpsServer.newRequest.connect(function (request) { + request.setResponseBody('Test') + request.sendResponse() + }) + view.settings.errorPageEnabled = false + } + + function init() { + verify(Shared.HttpsServer.start()) + } + + function cleanup() { + Shared.HttpsServer.stop() + view.deferError = false + view.acceptCertificate = false + spyError.clear() + } + + function test_error_data() { + return [ + { tag: 'reject', deferError: false, acceptCertificate: false, expectedContent: '' }, + { tag: 'defer_reject', deferError: true, acceptCertificate: false, expectedContent: '' }, + { tag: 'defer_accept', deferError: true, acceptCertificate: true, expectedContent: 'Test' }, + ] + } + + function test_error(data) { + view.deferError = data.deferError + view.acceptCertificate = data.acceptCertificate + view.url = Shared.HttpsServer.url() + + if (data.deferError) { + spyError.wait() + compare(spyError.count, 1) + compare('', view.getBodyText()) + + let error = spyError.signalArguments[0][0] + if (data.acceptCertificate) + error.ignoreCertificateError() + else + error.rejectCertificate() + } + + if (data.acceptCertificate) + verify(view.waitForLoadSucceeded()) + else + verify(view.waitForLoadFailed()) + + compare(spyError.count, 1) + compare(data.expectedContent, view.getBodyText()) + } + } +} diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro index 5c57f7ad9..6bec6dc0d 100644 --- a/tests/auto/quick/qmltests/qmltests.pro +++ b/tests/auto/quick/qmltests/qmltests.pro @@ -1,4 +1,5 @@ include(../tests.pri) +include(../../shared/https.pri) QT += qmltest diff --git a/tests/auto/quick/qmltests/tst_qmltests.cpp b/tests/auto/quick/qmltests/tst_qmltests.cpp index 9e8d25222..0d830931d 100644 --- a/tests/auto/quick/qmltests/tst_qmltests.cpp +++ b/tests/auto/quick/qmltests/tst_qmltests.cpp @@ -26,6 +26,8 @@ ** ****************************************************************************/ +#include + #include #include #include @@ -144,6 +146,8 @@ int main(int argc, char **argv) QTEST_SET_MAIN_SOURCE_PATH + qmlRegisterSingletonType("Test.Shared", 1, 0, "HttpsServer", [&] (QQmlEngine *, QJSEngine *) { return new HttpsServer; }); + int i = quick_test_main(argc, argv, "qmltests", QUICK_TEST_SOURCE_DIR); return i; } diff --git a/tests/auto/shared/httpreqrep.h b/tests/auto/shared/httpreqrep.h index bee8119eb..1666b17d0 100644 --- a/tests/auto/shared/httpreqrep.h +++ b/tests/auto/shared/httpreqrep.h @@ -40,7 +40,7 @@ class HttpReqRep : public QObject public: explicit HttpReqRep(QTcpSocket *socket, QObject *parent = nullptr); - void sendResponse(); + Q_INVOKABLE void sendResponse(); void close(); // Request parameters (only valid after requestReceived()) @@ -61,7 +61,7 @@ public: m_responseHeaders[key.toLower()] = std::move(value); } QByteArray responseBody() const { return m_responseBody; } - void setResponseBody(QByteArray content) + Q_INVOKABLE void setResponseBody(QByteArray content) { m_responseHeaders["content-length"] = QByteArray::number(content.size()); m_responseBody = std::move(content); -- cgit v1.2.3 From a29e79b0ef958e3672964f6e8699f669d17df82d Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Tue, 26 May 2020 15:43:52 +0200 Subject: Test: port qwebenginedownloaditem auto test to QRegularExpression Leftover from cffba828 Test: port tests to QRegularExpression Task-number: QTBUG-72596 Change-Id: I4009bc00f24b773539a674ad5f2ba0aad1cef04b Reviewed-by: Samuel Gaist --- .../widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tests/auto') diff --git a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp index 55d8ac6e8..39948c211 100644 --- a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp +++ b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp @@ -1016,8 +1016,10 @@ void tst_QWebEngineDownloadItem::downloadUniqueFilenameWithTimestamp() QRegularExpressionMatch match = fileNameCheck.match(downloadedFilePath); QVERIFY(match.hasMatch()); // ISO 8601 Date and time in UTC - QRegExp timestamp("^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9])([0-5][0-9])([0-5][0-9])([.][0-9]+)?(Z|[+-](?:2[0-3]|[01][0-9])[0-5][0-9])?$"); - QVERIFY(timestamp.exactMatch(match.captured(1))); + QRegularExpression timestamp("^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[" + "12][0-9])T(2[0-3]|[01][0-9])([0-5][0-9])([0-5][0-9])([.][0-9]" + "+)?(Z|[+-](?:2[0-3]|[01][0-9])[0-5][0-9])?$"); + QVERIFY(timestamp.match(match.captured(1)).hasMatch()); QCOMPARE(suggestedFileName, fileName); } } -- cgit v1.2.3