diff options
Diffstat (limited to 'tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp')
-rw-r--r-- | tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp | 811 |
1 files changed, 426 insertions, 385 deletions
diff --git a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp index e8ac9676f..4848038df 100644 --- a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp +++ b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp @@ -36,50 +36,150 @@ #include <QWebEngineProfile> #include <QWebEngineView> #include <httpserver.h> -#include <waitforsignal.h> - -static std::unique_ptr<HttpReqRep> waitForFaviconRequest(HttpServer *server) -{ - auto rr = waitForRequest(server); - if (!rr || - rr->requestMethod() != QByteArrayLiteral("GET") || - rr->requestPath() != QByteArrayLiteral("/favicon.ico")) - return nullptr; - rr->setResponseStatus(404); - rr->sendResponse(); - return std::move(rr); -} class tst_QWebEngineDownloads : public QObject { Q_OBJECT + +public: + enum UserAction { + SaveLink, + ClickLink, + }; + + enum FileAction { + FileIsDownloaded, + FileIsDisplayed, + }; + private Q_SLOTS: + void initTestCase(); + void init(); + void cleanup(); + void cleanupTestCase(); + void downloadLink_data(); void downloadLink(); + void downloadTwoLinks_data(); void downloadTwoLinks(); void downloadPage_data(); void downloadPage(); void downloadViaSetUrl(); void downloadFileNot1(); void downloadFileNot2(); -}; -enum DownloadTestUserAction { - SaveLink, - Navigate, +private: + void saveLink(QPoint linkPos); + void clickLink(QPoint linkPos); + void simulateUserAction(QPoint linkPos, UserAction action); + + QWebEngineDownloadItem::DownloadType expectedDownloadType( + UserAction userAction, + const QByteArray &contentDisposition = QByteArray()); + + HttpServer *m_server; + QWebEngineProfile *m_profile; + QWebEnginePage *m_page; + QWebEngineView *m_view; + QSet<QWebEngineDownloadItem *> m_downloads; }; -enum DownloadTestFileAction { - FileIsDownloaded, - FileIsDisplayed, +class ScopedConnection { +public: + ScopedConnection(QMetaObject::Connection connection) : m_connection(std::move(connection)) {} + ~ScopedConnection() { QObject::disconnect(m_connection); } +private: + QMetaObject::Connection m_connection; }; -Q_DECLARE_METATYPE(DownloadTestUserAction); -Q_DECLARE_METATYPE(DownloadTestFileAction); +Q_DECLARE_METATYPE(tst_QWebEngineDownloads::UserAction) +Q_DECLARE_METATYPE(tst_QWebEngineDownloads::FileAction) + +void tst_QWebEngineDownloads::initTestCase() +{ + m_server = new HttpServer(); + m_profile = new QWebEngineProfile; + m_profile->setHttpCacheType(QWebEngineProfile::NoCache); + connect(m_profile, &QWebEngineProfile::downloadRequested, [this](QWebEngineDownloadItem *item) { + m_downloads.insert(item); + connect(item, &QWebEngineDownloadItem::destroyed, [this, item](){ + m_downloads.remove(item); + }); + connect(item, &QWebEngineDownloadItem::finished, [this, item](){ + m_downloads.remove(item); + }); + }); + m_page = new QWebEnginePage(m_profile); + m_view = new QWebEngineView; + m_view->setPage(m_page); + m_view->show(); +} + +void tst_QWebEngineDownloads::init() +{ + QVERIFY(m_server->start()); +} + +void tst_QWebEngineDownloads::cleanup() +{ + QCOMPARE(m_downloads.count(), 0); + QVERIFY(m_server->stop()); +} + +void tst_QWebEngineDownloads::cleanupTestCase() +{ + delete m_view; + delete m_page; + delete m_profile; + delete m_server; +} + +void tst_QWebEngineDownloads::saveLink(QPoint linkPos) +{ + // Simulate right-clicking on link and choosing "save link as" from menu. + QSignalSpy menuSpy(m_view, &QWebEngineView::customContextMenuRequested); + m_view->setContextMenuPolicy(Qt::CustomContextMenu); + auto event1 = new QContextMenuEvent(QContextMenuEvent::Mouse, linkPos); + auto event2 = new QMouseEvent(QEvent::MouseButtonPress, linkPos, Qt::RightButton, {}, {}); + auto event3 = new QMouseEvent(QEvent::MouseButtonRelease, linkPos, Qt::RightButton, {}, {}); + QTRY_VERIFY(m_view->focusWidget()); + QWidget *renderWidget = m_view->focusWidget(); + QCoreApplication::postEvent(renderWidget, event1); + QCoreApplication::postEvent(renderWidget, event2); + QCoreApplication::postEvent(renderWidget, event3); + QTRY_COMPARE(menuSpy.count(), 1); + m_page->triggerAction(QWebEnginePage::DownloadLinkToDisk); +} + +void tst_QWebEngineDownloads::clickLink(QPoint linkPos) +{ + // Simulate left-clicking on link. + QTRY_VERIFY(m_view->focusWidget()); + QWidget *renderWidget = m_view->focusWidget(); + QTest::mouseClick(renderWidget, Qt::LeftButton, {}, linkPos); +} + +void tst_QWebEngineDownloads::simulateUserAction(QPoint linkPos, UserAction action) +{ + switch (action) { + case SaveLink: return saveLink(linkPos); + case ClickLink: return clickLink(linkPos); + } +} + +QWebEngineDownloadItem::DownloadType tst_QWebEngineDownloads::expectedDownloadType( + UserAction userAction, const QByteArray &contentDisposition) +{ + if (userAction == SaveLink) + return QWebEngineDownloadItem::UserRequested; + if (contentDisposition == QByteArrayLiteral("attachment")) + return QWebEngineDownloadItem::Attachment; + return QWebEngineDownloadItem::DownloadAttribute; +} void tst_QWebEngineDownloads::downloadLink_data() { - QTest::addColumn<DownloadTestUserAction>("userAction"); + QTest::addColumn<UserAction>("userAction"); QTest::addColumn<bool>("anchorHasDownloadAttribute"); QTest::addColumn<QByteArray>("fileName"); QTest::addColumn<QByteArray>("fileContents"); @@ -87,7 +187,7 @@ void tst_QWebEngineDownloads::downloadLink_data() QTest::addColumn<QByteArray>("fileMimeTypeDetected"); QTest::addColumn<QByteArray>("fileDisposition"); QTest::addColumn<bool>("fileHasReferer"); - QTest::addColumn<DownloadTestFileAction>("fileAction"); + QTest::addColumn<FileAction>("fileAction"); QTest::addColumn<QWebEngineDownloadItem::DownloadType>("downloadType"); // SaveLink should always trigger a download, even for empty files. @@ -100,8 +200,7 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::UserRequested; + /* fileAction */ << FileIsDownloaded; // SaveLink should always trigger a download, also for text files. QTest::newRow("save link to text file") @@ -113,8 +212,7 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("text/plain") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::UserRequested; + /* fileAction */ << FileIsDownloaded; // ... adding the "download" attribute should have no effect. QTest::newRow("save link to text file (attribute)") @@ -126,8 +224,7 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("text/plain") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::UserRequested; + /* fileAction */ << FileIsDownloaded; // ... adding the "attachment" content disposition should also have no effect. QTest::newRow("save link to text file (attachment)") @@ -139,8 +236,7 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("text/plain") /* fileDisposition */ << QByteArrayLiteral("attachment") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::UserRequested; + /* fileAction */ << FileIsDownloaded; // ... even adding both should have no effect. QTest::newRow("save link to text file (attribute+attachment)") @@ -152,12 +248,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("text/plain") /* fileDisposition */ << QByteArrayLiteral("attachment") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::UserRequested; + /* fileAction */ << FileIsDownloaded; // Navigating to an empty file should show an empty page. QTest::newRow("navigate to empty file") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << false /* fileName */ << QByteArrayLiteral("foo.txt") /* fileContents */ << QByteArrayLiteral("") @@ -165,12 +260,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDisplayed - /* downloadType */ << QWebEngineDownloadItem::UserRequested; + /* fileAction */ << FileIsDisplayed; // Navigating to a text file should show the text file. QTest::newRow("navigate to text file") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << false /* fileName */ << QByteArrayLiteral("foo.txt") /* fileContents */ << QByteArrayLiteral("bar") @@ -178,12 +272,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("text/plain") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDisplayed - /* downloadType */ << QWebEngineDownloadItem::UserRequested; + /* fileAction */ << FileIsDisplayed; // ... unless the link has the "download" attribute: then the file should be downloaded. QTest::newRow("navigate to text file (attribute)") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << true /* fileName */ << QByteArrayLiteral("foo.txt") /* fileContents */ << QByteArrayLiteral("bar") @@ -191,12 +284,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("text/plain") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::DownloadAttribute; + /* fileAction */ << FileIsDownloaded; // ... same with the content disposition header save for the download type. QTest::newRow("navigate to text file (attachment)") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << false /* fileName */ << QByteArrayLiteral("foo.txt") /* fileContents */ << QByteArrayLiteral("bar") @@ -204,12 +296,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("text/plain") /* fileDisposition */ << QByteArrayLiteral("attachment") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::Attachment; + /* fileAction */ << FileIsDownloaded; // ... and both. QTest::newRow("navigate to text file (attribute+attachment)") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << true /* fileName */ << QByteArrayLiteral("foo.txt") /* fileContents */ << QByteArrayLiteral("bar") @@ -217,12 +308,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("text/plain") /* fileDisposition */ << QByteArrayLiteral("attachment") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::Attachment; + /* fileAction */ << FileIsDownloaded; // The file's extension has no effect. QTest::newRow("navigate to supposed zip file") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << false /* fileName */ << QByteArrayLiteral("foo.zip") /* fileContents */ << QByteArrayLiteral("bar") @@ -230,12 +320,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDisplayed - /* downloadType */ << QWebEngineDownloadItem::DownloadAttribute; + /* fileAction */ << FileIsDisplayed; // ... the file's mime type however does. QTest::newRow("navigate to supposed zip file (application/zip)") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << false /* fileName */ << QByteArrayLiteral("foo.zip") /* fileContents */ << QByteArrayLiteral("bar") @@ -243,12 +332,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("application/zip") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::DownloadAttribute; + /* fileAction */ << FileIsDownloaded; // ... but we're not very picky about the exact type. QTest::newRow("navigate to supposed zip file (application/octet-stream)") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << false /* fileName */ << QByteArrayLiteral("foo.zip") /* fileContents */ << QByteArrayLiteral("bar") @@ -256,15 +344,14 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("application/octet-stream") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::DownloadAttribute; + /* fileAction */ << FileIsDownloaded; // empty zip file (consisting only of "end of central directory record") QByteArray zipFile = QByteArrayLiteral("PK\x05\x06") + QByteArray(18, 0); // The mime type is guessed automatically if not provided by the server. QTest::newRow("navigate to actual zip file") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << false /* fileName */ << QByteArrayLiteral("foo.zip") /* fileContents */ << zipFile @@ -272,12 +359,11 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("application/octet-stream") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::DownloadAttribute; + /* fileAction */ << FileIsDownloaded; // The mime type is not guessed automatically if provided by the server. QTest::newRow("navigate to actual zip file (application/zip)") - /* userAction */ << Navigate + /* userAction */ << ClickLink /* anchorHasDownloadAttribute */ << false /* fileName */ << QByteArrayLiteral("foo.zip") /* fileContents */ << zipFile @@ -285,13 +371,12 @@ void tst_QWebEngineDownloads::downloadLink_data() /* fileMimeTypeDetected */ << QByteArrayLiteral("application/zip") /* fileDisposition */ << QByteArrayLiteral("") /* fileHasReferer */ << true - /* fileAction */ << FileIsDownloaded - /* downloadType */ << QWebEngineDownloadItem::DownloadAttribute; + /* fileAction */ << FileIsDownloaded; } void tst_QWebEngineDownloads::downloadLink() { - QFETCH(DownloadTestUserAction, userAction); + QFETCH(UserAction, userAction); QFETCH(bool, anchorHasDownloadAttribute); QFETCH(QByteArray, fileName); QFETCH(QByteArray, fileContents); @@ -299,245 +384,225 @@ void tst_QWebEngineDownloads::downloadLink() QFETCH(QByteArray, fileMimeTypeDetected); QFETCH(QByteArray, fileDisposition); QFETCH(bool, fileHasReferer); - QFETCH(DownloadTestFileAction, fileAction); - QFETCH(QWebEngineDownloadItem::DownloadType, downloadType); - - HttpServer server; - QWebEngineProfile profile; - profile.setHttpCacheType(QWebEngineProfile::NoCache); - QWebEnginePage page(&profile); - QWebEngineView view; - view.setPage(&page); - - // 1. Load an HTML page with a link - // - // The only variation being whether the <a> element has a "download" - // attribute or not. - view.load(server.url()); - view.show(); - auto indexRR = waitForRequest(&server); - QVERIFY(indexRR); - QCOMPARE(indexRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(indexRR->requestPath(), QByteArrayLiteral("/")); - indexRR->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); - QByteArray html; - html += QByteArrayLiteral("<html><body><a href=\""); - html += fileName; - html += QByteArrayLiteral("\" "); - if (anchorHasDownloadAttribute) - html += QByteArrayLiteral("download"); - html += QByteArrayLiteral(">Link</a></body></html>"); - indexRR->setResponseBody(html); - indexRR->sendResponse(); - bool loadOk = false; - QVERIFY(waitForSignal(&page, &QWebEnginePage::loadFinished, [&](bool ok) { loadOk = ok; })); - QVERIFY(loadOk); - - // 1.1. Ignore favicon request - auto favIconRR = waitForFaviconRequest(&server); - QVERIFY(favIconRR); - - // 2. Simulate user action - // - // - Navigate: user left-clicks on link - // - SaveLink: user right-clicks on link and chooses "save link as" from menu - QTRY_VERIFY(view.focusWidget()); - QWidget *renderWidget = view.focusWidget(); - QPoint linkPos(10, 10); - if (userAction == SaveLink) { - view.setContextMenuPolicy(Qt::CustomContextMenu); - auto event1 = new QContextMenuEvent(QContextMenuEvent::Mouse, linkPos); - auto event2 = new QMouseEvent(QEvent::MouseButtonPress, linkPos, Qt::RightButton, {}, {}); - auto event3 = new QMouseEvent(QEvent::MouseButtonRelease, linkPos, Qt::RightButton, {}, {}); - QCoreApplication::postEvent(renderWidget, event1); - QCoreApplication::postEvent(renderWidget, event2); - QCoreApplication::postEvent(renderWidget, event3); - QVERIFY(waitForSignal(&view, &QWidget::customContextMenuRequested)); - page.triggerAction(QWebEnginePage::DownloadLinkToDisk); - } else - QTest::mouseClick(renderWidget, Qt::LeftButton, {}, linkPos); - - // 3. Deliver requested file - // - // Request/response headers vary. - auto fileRR = waitForRequest(&server); - QVERIFY(fileRR); - QCOMPARE(fileRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(fileRR->requestPath(), QByteArrayLiteral("/") + fileName); - if (fileHasReferer) - QCOMPARE(fileRR->requestHeader(QByteArrayLiteral("referer")), server.url().toEncoded()); - else - QCOMPARE(fileRR->requestHeader(QByteArrayLiteral("referer")), QByteArray()); - if (!fileDisposition.isEmpty()) - fileRR->setResponseHeader(QByteArrayLiteral("content-disposition"), fileDisposition); - if (!fileMimeTypeDeclared.isEmpty()) - fileRR->setResponseHeader(QByteArrayLiteral("content-type"), fileMimeTypeDeclared); - fileRR->setResponseBody(fileContents); - fileRR->sendResponse(); - - // 4a. File is displayed and not downloaded - end test - if (fileAction == FileIsDisplayed) { - QVERIFY(waitForSignal(&page, &QWebEnginePage::loadFinished, [&](bool ok) { loadOk = ok; })); - QVERIFY(loadOk); - return; - } + QFETCH(FileAction, fileAction); + + // Set up HTTP server + int indexRequestCount = 0; + int fileRequestCount = 0; + QByteArray fileRequestReferer; + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + if (rr->requestMethod() == "GET" && rr->requestPath() == "/") { + indexRequestCount++; + + rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); + QByteArray html; + html += QByteArrayLiteral("<html><body><a href=\""); + html += fileName; + html += QByteArrayLiteral("\" "); + if (anchorHasDownloadAttribute) + html += QByteArrayLiteral("download"); + html += QByteArrayLiteral(">Link</a></body></html>"); + rr->setResponseBody(html); + rr->sendResponse(); + } else if (rr->requestMethod() == "GET" && rr->requestPath() == "/" + fileName) { + fileRequestCount++; + fileRequestReferer = rr->requestHeader(QByteArrayLiteral("referer")); + + if (!fileDisposition.isEmpty()) + rr->setResponseHeader(QByteArrayLiteral("content-disposition"), fileDisposition); + if (!fileMimeTypeDeclared.isEmpty()) + rr->setResponseHeader(QByteArrayLiteral("content-type"), fileMimeTypeDeclared); + rr->setResponseBody(fileContents); + rr->sendResponse(); + } else { + rr->setResponseStatus(404); + rr->sendResponse(); + } + }); - // 4b. File is downloaded - check QWebEngineDownloadItem attributes + // Set up profile and download handler QTemporaryDir tmpDir; QVERIFY(tmpDir.isValid()); QByteArray slashFileName = QByteArrayLiteral("/") + fileName; QString suggestedPath = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + slashFileName; QString downloadPath = tmpDir.path() + slashFileName; - QUrl downloadUrl = server.url(slashFileName); - QWebEngineDownloadItem *downloadItem = nullptr; - QVERIFY(waitForSignal(&profile, &QWebEngineProfile::downloadRequested, - [&](QWebEngineDownloadItem *item) { + QUrl downloadUrl = m_server->url(slashFileName); + int acceptedCount = 0; + int finishedCount = 0; + ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadRequested); QCOMPARE(item->isFinished(), false); QCOMPARE(item->totalBytes(), -1); QCOMPARE(item->receivedBytes(), 0); QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); - QCOMPARE(item->type(), downloadType); + QCOMPARE(item->type(), expectedDownloadType(userAction, fileDisposition)); QCOMPARE(item->isSavePageDownload(), false); QCOMPARE(item->mimeType(), QString(fileMimeTypeDetected)); QCOMPARE(item->path(), suggestedPath); QCOMPARE(item->savePageFormat(), QWebEngineDownloadItem::UnknownSaveFormat); QCOMPARE(item->url(), downloadUrl); + + connect(item, &QWebEngineDownloadItem::finished, [&, item]() { + QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadCompleted); + QCOMPARE(item->isFinished(), true); + QCOMPARE(item->totalBytes(), fileContents.size()); + QCOMPARE(item->receivedBytes(), fileContents.size()); + QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); + QCOMPARE(item->type(), expectedDownloadType(userAction, fileDisposition)); + QCOMPARE(item->isSavePageDownload(), false); + QCOMPARE(item->mimeType(), QString(fileMimeTypeDetected)); + QCOMPARE(item->path(), downloadPath); + QCOMPARE(item->savePageFormat(), QWebEngineDownloadItem::UnknownSaveFormat); + QCOMPARE(item->url(), downloadUrl); + + finishedCount++; + }); item->setPath(downloadPath); item->accept(); - downloadItem = item; - })); - QVERIFY(downloadItem); - bool finishOk = false; - QVERIFY(waitForSignal(downloadItem, &QWebEngineDownloadItem::finished, [&]() { - auto item = downloadItem; - QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadCompleted); - QCOMPARE(item->isFinished(), true); - QCOMPARE(item->totalBytes(), fileContents.size()); - QCOMPARE(item->receivedBytes(), fileContents.size()); - QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); - QCOMPARE(item->type(), downloadType); - QCOMPARE(item->isSavePageDownload(), false); - QCOMPARE(item->mimeType(), QString(fileMimeTypeDetected)); - QCOMPARE(item->path(), downloadPath); - QCOMPARE(item->savePageFormat(), QWebEngineDownloadItem::UnknownSaveFormat); - QCOMPARE(item->url(), downloadUrl); - finishOk = true; - })); - QVERIFY(finishOk); - // 5. Check actual file contents + acceptedCount++; + }); + + // Load an HTML page with a link + // + // The only variation being whether the <a> element has a "download" + // attribute or not. + QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + m_view->load(m_server->url()); + QTRY_COMPARE(loadSpy.count(), 1); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + QCOMPARE(indexRequestCount, 1); + + simulateUserAction(QPoint(10, 10), userAction); + + // If file is expected to be displayed and not downloaded then end test + if (fileAction == FileIsDisplayed) { + QTRY_COMPARE(loadSpy.count(), 1); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + QCOMPARE(acceptedCount, 0); + return; + } + + // Otherwise file is downloaded + QTRY_COMPARE(acceptedCount, 1); + QTRY_COMPARE(finishedCount, 1); + QCOMPARE(fileRequestCount, 1); + if (fileHasReferer) + QCOMPARE(fileRequestReferer, m_server->url().toEncoded()); + else + QCOMPARE(fileRequestReferer, QByteArray()); QFile file(downloadPath); QVERIFY(file.open(QIODevice::ReadOnly)); QCOMPARE(file.readAll(), fileContents); } +void tst_QWebEngineDownloads::downloadTwoLinks_data() +{ + QTest::addColumn<UserAction>("action1"); + QTest::addColumn<UserAction>("action2"); + QTest::newRow("Save+Save") << SaveLink << SaveLink; + QTest::newRow("Save+Click") << SaveLink << ClickLink; + QTest::newRow("Click+Save") << ClickLink << SaveLink; + QTest::newRow("Click+Click") << ClickLink << ClickLink; +} + void tst_QWebEngineDownloads::downloadTwoLinks() { - HttpServer server; - QSignalSpy requestSpy(&server, &HttpServer::newRequest); - QList<HttpReqRep*> results; - connect(&server, &HttpServer::newRequest, [&](HttpReqRep *rr) { - rr->setParent(nullptr); - results.append(rr); + QFETCH(UserAction, action1); + QFETCH(UserAction, action2); + + // Set up HTTP server + int file1RequestCount = 0; + int file2RequestCount = 0; + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + if (rr->requestMethod() == "GET" && rr->requestPath() == "/") { + rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); + rr->setResponseBody(QByteArrayLiteral("<html><body><a href=\"file1\" download>Link1</a><br/><a href=\"file2\">Link2</a></body></html>")); + rr->sendResponse(); + } else if (rr->requestMethod() == "GET" && rr->requestPath() == "/file1") { + file1RequestCount++; + rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/plain")); + rr->setResponseBody(QByteArrayLiteral("file1")); + rr->sendResponse(); + } else if (rr->requestMethod() == "GET" && rr->requestPath() == "/file2") { + file2RequestCount++; + rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/plain")); + rr->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment")); + rr->setResponseBody(QByteArrayLiteral("file2")); + rr->sendResponse(); + } else { + rr->setResponseStatus(404); + rr->sendResponse(); + } }); + // Set up profile and download handler QTemporaryDir tmpDir; QVERIFY(tmpDir.isValid()); QString standardDir = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation); - - QWebEngineProfile profile; - profile.setHttpCacheType(QWebEngineProfile::NoCache); - QList<QPointer<QWebEngineDownloadItem>> downloadItems; - connect(&profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { + int acceptedCount = 0; + int finishedCount = 0; + ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadRequested); QCOMPARE(item->isFinished(), false); QCOMPARE(item->totalBytes(), -1); QCOMPARE(item->receivedBytes(), 0); QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); + QCOMPARE(item->savePageFormat(), QWebEngineDownloadItem::UnknownSaveFormat); + QCOMPARE(item->mimeType(), QStringLiteral("text/plain")); QString filePart = QChar('/') + item->url().fileName(); QCOMPARE(item->path(), standardDir + filePart); + + // type() is broken due to race condition in DownloadManagerDelegateQt + if (action1 == ClickLink && action2 == ClickLink) { + if (filePart == QStringLiteral("/file1")) + QCOMPARE(item->type(), expectedDownloadType(action1)); + else if (filePart == QStringLiteral("/file2")) + QCOMPARE(item->type(), expectedDownloadType(action2, QByteArrayLiteral("attachment"))); + else + QFAIL(qPrintable("Unexpected file name: " + filePart)); + } + + connect(item, &QWebEngineDownloadItem::finished, [&]() { + finishedCount++; + }); item->setPath(tmpDir.path() + filePart); item->accept(); - downloadItems.append(item); + + acceptedCount++; }); - QWebEnginePage page(&profile); - QWebEngineView view; - view.setPage(&page); - - view.load(server.url()); - view.show(); - QTRY_COMPARE(requestSpy.count(), 1); - std::unique_ptr<HttpReqRep> indexRR(results.takeFirst()); - QVERIFY(indexRR); - QCOMPARE(indexRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(indexRR->requestPath(), QByteArrayLiteral("/")); - indexRR->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); - indexRR->setResponseBody(QByteArrayLiteral("<html><body><a href=\"file1\" download>Link1</a><br/><a href=\"file2\">Link2</a></body></html>")); - indexRR->sendResponse(); - bool loadOk = false; - QVERIFY(waitForSignal(&page, &QWebEnginePage::loadFinished, [&](bool ok){ loadOk = ok; })); - QVERIFY(loadOk); - - QTRY_COMPARE(requestSpy.count(), 2); - std::unique_ptr<HttpReqRep> favIconRR(results.takeFirst()); - QVERIFY(favIconRR); - favIconRR->setResponseStatus(404); - favIconRR->sendResponse(); - - QTRY_VERIFY(view.focusWidget()); - QWidget *renderWidget = view.focusWidget(); - QTest::mouseClick(renderWidget, Qt::LeftButton, {}, QPoint(10, 10)); - QTest::mouseClick(renderWidget, Qt::LeftButton, {}, QPoint(10, 30)); - - QTRY_VERIFY(requestSpy.count() >= 3); - std::unique_ptr<HttpReqRep> file1RR(results.takeFirst()); - QVERIFY(file1RR); - QCOMPARE(file1RR->requestMethod(), QByteArrayLiteral("GET")); - QTRY_COMPARE(requestSpy.count(), 4); - std::unique_ptr<HttpReqRep> file2RR(results.takeFirst()); - QVERIFY(file2RR); - QCOMPARE(file2RR->requestMethod(), QByteArrayLiteral("GET")); - - // Handle one request overtaking the other - if (file1RR->requestPath() == QByteArrayLiteral("/file2")) - std::swap(file1RR, file2RR); - - QCOMPARE(file1RR->requestPath(), QByteArrayLiteral("/file1")); - QCOMPARE(file2RR->requestPath(), QByteArrayLiteral("/file2")); - - file1RR->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/plain")); - file1RR->setResponseBody(QByteArrayLiteral("file1")); - file1RR->sendResponse(); - file2RR->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/plain")); - file2RR->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment")); - file2RR->setResponseBody(QByteArrayLiteral("file2")); - file2RR->sendResponse(); - - // Now wait for downloadRequested signals: - QTRY_VERIFY(downloadItems.count() >= 2); - QScopedPointer<QWebEngineDownloadItem> item1(downloadItems.takeFirst()); - QScopedPointer<QWebEngineDownloadItem> item2(downloadItems.takeFirst()); - QVERIFY(item1); - QVERIFY(item2); - - // Handle one request overtaking the other - if (item1->url().fileName() == QByteArrayLiteral("file2")) - qSwap(item1, item2); - - QCOMPARE(item1->type(), QWebEngineDownloadItem::DownloadAttribute); - QCOMPARE(item1->mimeType(), QStringLiteral("text/plain")); - QCOMPARE(item1->savePageFormat(), QWebEngineDownloadItem::UnknownSaveFormat); - QCOMPARE(item1->url(), server.url(QByteArrayLiteral("/file1"))); - QTRY_COMPARE(item1->state(), QWebEngineDownloadItem::DownloadCompleted); - - QCOMPARE(item2->type(), QWebEngineDownloadItem::Attachment); - QCOMPARE(item2->mimeType(), QStringLiteral("text/plain")); - QCOMPARE(item2->savePageFormat(), QWebEngineDownloadItem::UnknownSaveFormat); - QCOMPARE(item2->url(), server.url(QByteArrayLiteral("/file2"))); - QTRY_COMPARE(item2->state(), QWebEngineDownloadItem::DownloadCompleted); + QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + m_view->load(m_server->url()); + QTRY_COMPARE(loadSpy.count(), 1); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + + // Trigger downloads + simulateUserAction(QPoint(10, 10), action1); + simulateUserAction(QPoint(10, 30), action2); + + // Wait for downloads + if (action1 == action2 && action1 == ClickLink) { + // With two clicks, sometimes both files get downloaded, sometimes only + // the second file, depending on the timing. This is expected and + // follows Chromium's behavior. We check here only that the second file + // is downloaded correctly (and that we do not crash). + // + // The first download may be aborted before or after the HTTP request is + // made. In the latter case we will have both a file1 and a file2 + // request, but still only one accepted download. + QTRY_COMPARE(file2RequestCount, 1); + QTRY_VERIFY(acceptedCount >= 1); + QTRY_VERIFY(finishedCount >= 1); + QTRY_COMPARE(m_downloads.count(), 0); + } else { + // Otherwise both files should always be downloaded correctly. + QTRY_COMPARE(file1RequestCount, 1); + QTRY_COMPARE(file2RequestCount, 1); + QTRY_COMPARE(acceptedCount, 2); + QTRY_COMPARE(finishedCount, 2); + } } void tst_QWebEngineDownloads::downloadPage_data() @@ -552,37 +617,28 @@ void tst_QWebEngineDownloads::downloadPage() { QFETCH(QWebEngineDownloadItem::SavePageFormat, savePageFormat); - HttpServer server; - QWebEngineProfile profile; - QWebEnginePage page(&profile); - QWebEngineView view; - view.setPage(&page); - - view.load(server.url()); - view.show(); - auto indexRR = waitForRequest(&server); - QVERIFY(indexRR); - QCOMPARE(indexRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(indexRR->requestPath(), QByteArrayLiteral("/")); - indexRR->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); - indexRR->setResponseBody(QByteArrayLiteral("<html><body>Hello</body></html>")); - indexRR->sendResponse(); - bool loadOk = false; - QVERIFY(waitForSignal(&page, &QWebEnginePage::loadFinished, [&](bool ok){ loadOk = ok; })); - QVERIFY(loadOk); - - auto favIconRR = waitForFaviconRequest(&server); - QVERIFY(favIconRR); + // Set up HTTP server + int indexRequestCount = 0; + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + if (rr->requestMethod() == "GET" && rr->requestPath() == "/") { + indexRequestCount++; + rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); + rr->setResponseBody(QByteArrayLiteral("<html><body>Hello</body></html>")); + rr->sendResponse(); + } else { + rr->setResponseStatus(404); + rr->sendResponse(); + } + }); + // Set up profile and download handler QTemporaryDir tmpDir; QVERIFY(tmpDir.isValid()); QString downloadPath = tmpDir.path() + QStringLiteral("/test.html"); - page.save(downloadPath, savePageFormat); - - QWebEngineDownloadItem *downloadItem = nullptr; - QUrl downloadUrl = server.url("/"); - QVERIFY(waitForSignal(&profile, &QWebEngineProfile::downloadRequested, - [&](QWebEngineDownloadItem *item) { + QUrl downloadUrl = m_server->url("/"); + int acceptedCount = 0; + int finishedCount = 0; + ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadInProgress); QCOMPARE(item->isFinished(), false); QCOMPARE(item->totalBytes(), -1); @@ -590,33 +646,43 @@ void tst_QWebEngineDownloads::downloadPage() QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); QCOMPARE(item->type(), QWebEngineDownloadItem::SavePage); QCOMPARE(item->isSavePageDownload(), true); - // FIXME why is mimeType always the same? + // FIXME(juvaldma): why is mimeType always the same? QCOMPARE(item->mimeType(), QStringLiteral("application/x-mimearchive")); QCOMPARE(item->path(), downloadPath); QCOMPARE(item->savePageFormat(), savePageFormat); QCOMPARE(item->url(), downloadUrl); // no need to call item->accept() - downloadItem = item; - })); - QVERIFY(downloadItem); - bool finishOk = false; - QVERIFY(waitForSignal(downloadItem, &QWebEngineDownloadItem::finished, [&]() { - auto item = downloadItem; - QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadCompleted); - QCOMPARE(item->isFinished(), true); - QCOMPARE(item->totalBytes(), item->receivedBytes()); - QVERIFY(item->receivedBytes() > 0); - QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); - QCOMPARE(item->type(), QWebEngineDownloadItem::SavePage); - QCOMPARE(item->isSavePageDownload(), true); - QCOMPARE(item->mimeType(), QStringLiteral("application/x-mimearchive")); - QCOMPARE(item->path(), downloadPath); - QCOMPARE(item->savePageFormat(), savePageFormat); - QCOMPARE(item->url(), downloadUrl); - finishOk = true; - })); - QVERIFY(finishOk); + connect(item, &QWebEngineDownloadItem::finished, [&, item]() { + QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadCompleted); + QCOMPARE(item->isFinished(), true); + QCOMPARE(item->totalBytes(), item->receivedBytes()); + QVERIFY(item->receivedBytes() > 0); + QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); + QCOMPARE(item->type(), QWebEngineDownloadItem::SavePage); + QCOMPARE(item->isSavePageDownload(), true); + QCOMPARE(item->mimeType(), QStringLiteral("application/x-mimearchive")); + QCOMPARE(item->path(), downloadPath); + QCOMPARE(item->savePageFormat(), savePageFormat); + QCOMPARE(item->url(), downloadUrl); + + finishedCount++; + }); + + acceptedCount++; + }); + + // Load some HTML + QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + m_page->load(m_server->url()); + QTRY_COMPARE(loadSpy.count(), 1); + QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + QCOMPARE(indexRequestCount, 1); + + // Save some HTML + m_page->save(downloadPath, savePageFormat); + QTRY_COMPARE(acceptedCount, 1); + QTRY_COMPARE(finishedCount, 1); QFile file(downloadPath); QVERIFY(file.exists()); } @@ -626,31 +692,33 @@ void tst_QWebEngineDownloads::downloadViaSetUrl() // Reproduce the scenario described in QTBUG-63388 by triggering downloads // of the same file multiple times via QWebEnginePage::setUrl - HttpServer server; - QWebEngineProfile profile; - QWebEnginePage page(&profile); - QSignalSpy loadSpy(&page, &QWebEnginePage::loadFinished); - QSignalSpy urlSpy(&page, &QWebEnginePage::urlChanged); - const QUrl indexUrl = server.url(); - const QUrl fileUrl = server.url(QByteArrayLiteral("/file")); - - // Set up the test scenario by trying to load some unrelated HTML. - - page.setUrl(indexUrl); - - auto indexRR = waitForRequest(&server); - QVERIFY(indexRR); - QCOMPARE(indexRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(indexRR->requestPath(), QByteArrayLiteral("/")); - indexRR->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); - indexRR->setResponseBody(QByteArrayLiteral("<html><body>Hello</body></html>")); - indexRR->sendResponse(); + // Set up HTTP server + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + if (rr->requestMethod() == "GET" && rr->requestPath() == "/") { + rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("text/html")); + rr->setResponseBody(QByteArrayLiteral("<html><body>Hello</body></html>")); + rr->sendResponse(); + } else if (rr->requestMethod() == "GET" && rr->requestPath() == "/file") { + rr->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment")); + rr->setResponseBody(QByteArrayLiteral("redacted")); + rr->sendResponse(); + } else { + rr->setResponseStatus(404); + rr->sendResponse(); + } + }); - auto indexFavRR = waitForFaviconRequest(&server); - QVERIFY(indexFavRR); - indexRR.reset(); - indexFavRR.reset(); + // Set up profile and download handler + QVector<QUrl> downloadUrls; + ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { + downloadUrls.append(item->url()); + }); + // Set up the test scenario by trying to load some unrelated HTML. + QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + QSignalSpy urlSpy(m_page, &QWebEnginePage::urlChanged); + const QUrl indexUrl = m_server->url(); + m_page->setUrl(indexUrl); QTRY_COMPARE(loadSpy.count(), 1); QTRY_COMPARE(urlSpy.count(), 1); QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); @@ -658,37 +726,18 @@ void tst_QWebEngineDownloads::downloadViaSetUrl() // Download files via setUrl. With QTBUG-63388 after the first iteration the // downloads would be triggered for indexUrl and not fileUrl. - - QVector<QUrl> downloadUrls; - QObject::connect(&profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { - downloadUrls.append(item->url()); - }); - + const QUrl fileUrl = m_server->url(QByteArrayLiteral("/file")); for (int i = 0; i != 3; ++i) { - page.setUrl(fileUrl); - QCOMPARE(page.url(), fileUrl); - - auto fileRR = waitForRequest(&server); - QVERIFY(fileRR); - QCOMPARE(fileRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(fileRR->requestPath(), QByteArrayLiteral("/file")); - fileRR->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment")); - fileRR->setResponseBody(QByteArrayLiteral("redacted")); - fileRR->sendResponse(); - -// Since 63 we no longer get favicon requests here: -// auto fileFavRR = waitForFaviconRequest(&server); -// QVERIFY(fileFavRR); - + m_page->setUrl(fileUrl); + QCOMPARE(m_page->url(), fileUrl); QTRY_COMPARE(loadSpy.count(), 1); QTRY_COMPARE(urlSpy.count(), 2); QTRY_COMPARE(downloadUrls.count(), 1); - fileRR.reset(); QCOMPARE(loadSpy.takeFirst().value(0).toBool(), false); QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), fileUrl); QCOMPARE(urlSpy.takeFirst().value(0).toUrl(), indexUrl); QCOMPARE(downloadUrls.takeFirst(), fileUrl); - QCOMPARE(page.url(), indexUrl); + QCOMPARE(m_page->url(), indexUrl); } } @@ -696,26 +745,22 @@ void tst_QWebEngineDownloads::downloadFileNot1() { // Trigger file download via download() but don't accept(). - HttpServer server; - QWebEngineProfile profile; - QWebEnginePage page(&profile); - const auto filePath = QByteArrayLiteral("/file"); - const auto fileUrl = server.url(filePath); - - page.download(fileUrl); - auto fileRR = waitForRequest(&server); - QVERIFY(fileRR); - QCOMPARE(fileRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(fileRR->requestPath(), filePath); - fileRR->sendResponse(); + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + rr->setResponseStatus(404); + rr->sendResponse(); + }); QPointer<QWebEngineDownloadItem> downloadItem; - QVERIFY(waitForSignal(&profile, &QWebEngineProfile::downloadRequested, - [&](QWebEngineDownloadItem *item) { + int downloadCount = 0; + ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { QVERIFY(item); QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadRequested); downloadItem = item; - })); + downloadCount++; + }); + + m_page->download(m_server->url(QByteArrayLiteral("/file"))); + QTRY_COMPARE(downloadCount, 1); QVERIFY(!downloadItem); } @@ -723,27 +768,23 @@ void tst_QWebEngineDownloads::downloadFileNot2() { // Trigger file download via download() but call cancel() instead of accept(). - HttpServer server; - QWebEngineProfile profile; - QWebEnginePage page(&profile); - const auto filePath = QByteArrayLiteral("/file"); - const auto fileUrl = server.url(filePath); - - page.download(fileUrl); - auto fileRR = waitForRequest(&server); - QVERIFY(fileRR); - QCOMPARE(fileRR->requestMethod(), QByteArrayLiteral("GET")); - QCOMPARE(fileRR->requestPath(), filePath); - fileRR->sendResponse(); + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + rr->setResponseStatus(404); + rr->sendResponse(); + }); QPointer<QWebEngineDownloadItem> downloadItem; - QVERIFY(waitForSignal(&profile, &QWebEngineProfile::downloadRequested, - [&](QWebEngineDownloadItem *item) { + int downloadCount = 0; + ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { QVERIFY(item); QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadRequested); item->cancel(); downloadItem = item; - })); + downloadCount++; + }); + + m_page->download(m_server->url(QByteArrayLiteral("/file"))); + QTRY_COMPARE(downloadCount, 1); QVERIFY(downloadItem); QCOMPARE(downloadItem->state(), QWebEngineDownloadItem::DownloadCancelled); } |