summaryrefslogtreecommitdiffstats
path: root/tests/auto
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-05-14 10:49:00 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-05-15 17:26:19 +0200
commitbc6df3888128e3a0e0d4e2f8a69970ac36d8abe7 (patch)
tree2cb49ad5fffa0f2011b3d98faa363f105135901e /tests/auto
parent10e66c6dd0b8a8dd17252d6408c13b689fac6995 (diff)
parent585da6f74012bd09e8a873080e368cff99c97cbf (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts: src/pdf/quick/qquickpdfselection_p.h Change-Id: I6eec37a01347c2d47cbfc1114326dfc6b58719ff
Diffstat (limited to 'tests/auto')
-rw-r--r--tests/auto/quick/qmltests/data/tst_audioMuted.qml63
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro1
-rw-r--r--tests/auto/widgets/proxy/proxy_server.cpp18
-rw-r--r--tests/auto/widgets/proxy/proxy_server.h7
-rw-r--r--tests/auto/widgets/proxy/tst_proxy.cpp35
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp190
-rw-r--r--tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp22
-rw-r--r--tests/auto/widgets/util.h13
8 files changed, 327 insertions, 22 deletions
diff --git a/tests/auto/quick/qmltests/data/tst_audioMuted.qml b/tests/auto/quick/qmltests/data/tst_audioMuted.qml
new file mode 100644
index 000000000..c626d07a0
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_audioMuted.qml
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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.0
+import QtTest 1.0
+import QtWebEngine 1.4
+
+TestWebEngineView {
+ id: view
+ width: 400
+ height: 400
+
+ SignalSpy {
+ id: spy
+ target: view
+ signalName: "audioMutedChanged"
+ }
+
+ TestCase {
+ id: test
+ name: "WebEngineViewAudioMuted"
+
+ function test_audioMuted() {
+ compare(view.audioMuted, false);
+ view.audioMuted = true;
+ view.url = "about:blank";
+ verify(view.waitForLoadSucceeded());
+ compare(view.audioMuted, true);
+ compare(spy.count, 1);
+ compare(spy.signalArguments[0][0], true);
+ view.audioMuted = false;
+ compare(view.audioMuted, false);
+ compare(spy.count, 2);
+ compare(spy.signalArguments[1][0], false);
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index 0b3ff7c7e..5c57f7ad9 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -31,6 +31,7 @@ OTHER_FILES += \
$$PWD/data/titleupdate.js \
$$PWD/data/tst_action.qml \
$$PWD/data/tst_activeFocusOnPress.qml \
+ $$PWD/data/tst_audioMuted.qml \
$$PWD/data/tst_contextMenu.qml \
$$PWD/data/tst_desktopBehaviorLoadHtml.qml \
$$PWD/data/tst_download.qml \
diff --git a/tests/auto/widgets/proxy/proxy_server.cpp b/tests/auto/widgets/proxy/proxy_server.cpp
index 55f014914..3bf915609 100644
--- a/tests/auto/widgets/proxy/proxy_server.cpp
+++ b/tests/auto/widgets/proxy/proxy_server.cpp
@@ -42,8 +42,16 @@ void ProxyServer::setCredentials(const QByteArray &user, const QByteArray passwo
m_auth.append(QChar(':'));
m_auth.append(password);
m_auth = m_auth.toBase64();
+ m_authenticate = true;
}
+void ProxyServer::setCookie(const QByteArray &cookie)
+{
+ m_cookie.append(QByteArrayLiteral("Cookie: "));
+ m_cookie.append(cookie);
+}
+
+
bool ProxyServer::isListening()
{
return m_server.isListening();
@@ -75,7 +83,7 @@ void ProxyServer::handleReadReady()
if (!m_data.endsWith("\r\n\r\n"))
return;
- if (!m_data.contains(QByteArrayLiteral("Proxy-Authorization: Basic"))) {
+ if (m_authenticate && !m_data.contains(QByteArrayLiteral("Proxy-Authorization: Basic"))) {
socket->write("HTTP/1.1 407 Proxy Authentication Required\nProxy-Authenticate: "
"Basic realm=\"Proxy requires authentication\"\r\n"
"content-length: 0\r\n"
@@ -83,8 +91,12 @@ void ProxyServer::handleReadReady()
return;
}
- if (m_data.contains(m_auth)) {
- emit success();
+ if (m_authenticate && m_data.contains(m_auth)) {
+ emit authenticationSuccess();
+ }
+
+ if (m_data.contains(m_cookie)) {
+ emit cookieMatch();
}
m_data.clear();
}
diff --git a/tests/auto/widgets/proxy/proxy_server.h b/tests/auto/widgets/proxy/proxy_server.h
index cb7c30600..7bc7b100b 100644
--- a/tests/auto/widgets/proxy/proxy_server.h
+++ b/tests/auto/widgets/proxy/proxy_server.h
@@ -39,6 +39,7 @@ class ProxyServer : public QObject
public:
explicit ProxyServer(QObject *parent = nullptr);
void setCredentials(const QByteArray &user, const QByteArray password);
+ void setCookie(const QByteArray &cookie);
bool isListening();
public slots:
@@ -49,11 +50,15 @@ private slots:
void handleReadReady();
signals:
- void success();
+ void authenticationSuccess();
+ void cookieMatch();
+
private:
QByteArray m_data;
QTcpServer m_server;
QByteArray m_auth;
+ QByteArray m_cookie;
+ bool m_authenticate = false;
};
#endif // PROXY_SERVER_H
diff --git a/tests/auto/widgets/proxy/tst_proxy.cpp b/tests/auto/widgets/proxy/tst_proxy.cpp
index 5f5dec016..c3e3c88a4 100644
--- a/tests/auto/widgets/proxy/tst_proxy.cpp
+++ b/tests/auto/widgets/proxy/tst_proxy.cpp
@@ -32,6 +32,17 @@
#include <QNetworkProxy>
#include <QWebEnginePage>
#include <QWebEngineView>
+#include <QWebEngineUrlRequestInterceptor>
+
+
+struct Interceptor : public QWebEngineUrlRequestInterceptor
+{
+ Interceptor(const QByteArray cookie):m_cookie(cookie){};
+ void interceptRequest(QWebEngineUrlRequestInfo &info) override {
+ info.setHttpHeader(QByteArray("Cookie"), m_cookie);
+ };
+ QByteArray m_cookie;
+};
class tst_Proxy : public QObject {
@@ -41,8 +52,10 @@ public:
private slots:
void proxyAuthentication();
+ void forwardCookie();
};
+
void tst_Proxy::proxyAuthentication()
{
QByteArray user(QByteArrayLiteral("test"));
@@ -59,11 +72,31 @@ void tst_Proxy::proxyAuthentication()
server.run();
QTRY_VERIFY2(server.isListening(), "Could not setup authentication server");
QWebEnginePage page;
- QSignalSpy successSpy(&server, &ProxyServer::success);
+ QSignalSpy successSpy(&server, &ProxyServer::authenticationSuccess);
page.load(QUrl("http://www.qt.io"));
QTRY_VERIFY2(successSpy.count() > 0, "Could not get authentication token");
}
+void tst_Proxy::forwardCookie()
+{
+ QNetworkProxy proxy;
+ proxy.setType(QNetworkProxy::HttpProxy);
+ proxy.setHostName("localhost");
+ proxy.setPort(5555);
+ QNetworkProxy::setApplicationProxy(proxy);
+ ProxyServer server;
+ QByteArray cookie("foo=bar; sessionToken=123");
+ server.setCookie(cookie);
+ server.run();
+ QTRY_VERIFY2(server.isListening(), "Could not setup proxy server");
+ Interceptor interceptor(cookie);
+ QWebEnginePage page;
+ page.setUrlRequestInterceptor(&interceptor);
+ QSignalSpy cookieSpy(&server, &ProxyServer::cookieMatch);
+ page.load(QUrl("http://www.qt.io"));
+ QTRY_VERIFY2(cookieSpy.count() > 0, "Could not get cookie");
+}
+
#include "tst_proxy.moc"
QTEST_MAIN(tst_Proxy)
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 098656390..92ee791db 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -197,6 +197,8 @@ private Q_SLOTS:
void dataURLFragment();
void devTools();
void openLinkInDifferentProfile();
+ void openLinkInNewPage_data();
+ void openLinkInNewPage();
void triggerActionWithoutMenu();
void dynamicFrame();
@@ -204,6 +206,7 @@ private Q_SLOTS:
void notificationRequest();
void sendNotification();
void contentsSize();
+ void notificationPermission();
void setLifecycleState();
void setVisible();
@@ -227,6 +230,7 @@ private Q_SLOTS:
void renderProcessCrashed();
void renderProcessPid();
void backgroundColor();
+ void audioMuted();
private:
static QPoint elementCenter(QWebEnginePage *page, const QString &id);
@@ -3378,6 +3382,162 @@ void tst_QWebEnginePage::openLinkInDifferentProfile()
QVERIFY(spy2.takeFirst().value(0).toBool());
}
+// What does createWindow do?
+enum class OpenLinkInNewPageDecision {
+ // Returns nullptr,
+ ReturnNull,
+ // Returns this,
+ ReturnSelf,
+ // Returns page != this
+ ReturnOther,
+};
+
+// What causes createWindow to be called?
+enum class OpenLinkInNewPageCause {
+ // User clicks on a link with target=_blank.
+ TargetBlank,
+ // User clicks with MiddleButton.
+ MiddleClick,
+};
+
+// What happens after createWindow?
+enum class OpenLinkInNewPageEffect {
+ // The navigation request disappears into the ether.
+ Blocked,
+ // The navigation request becomes a navigation in the original page.
+ LoadInSelf,
+ // The navigation request becomes a navigation in a different page.
+ LoadInOther,
+};
+
+Q_DECLARE_METATYPE(OpenLinkInNewPageCause)
+Q_DECLARE_METATYPE(OpenLinkInNewPageDecision)
+Q_DECLARE_METATYPE(OpenLinkInNewPageEffect)
+
+void tst_QWebEnginePage::openLinkInNewPage_data()
+{
+ using Decision = OpenLinkInNewPageDecision;
+ using Cause = OpenLinkInNewPageCause;
+ using Effect = OpenLinkInNewPageEffect;
+
+ QTest::addColumn<Decision>("decision");
+ QTest::addColumn<Cause>("cause");
+ QTest::addColumn<Effect>("effect");
+
+ // Note that the meaning of returning nullptr from createWindow is not
+ // consistent between the TargetBlank and MiddleClick scenarios.
+ //
+ // With TargetBlank, the open-in-new-page disposition comes from the HTML
+ // target attribute; something the user is probably not aware of. Returning
+ // nullptr is interpreted as a decision by the app to block an unwanted
+ // popup.
+ //
+ // With MiddleClick, the open-in-new-page disposition comes from the user's
+ // explicit intent. Returning nullptr is then interpreted as a failure by
+ // the app to fulfill this intent, which we try to compensate by ignoring
+ // the disposition and performing the navigation request normally.
+
+ QTest::newRow("BlockPopup") << Decision::ReturnNull << Cause::TargetBlank << Effect::Blocked;
+ QTest::newRow("IgnoreIntent") << Decision::ReturnNull << Cause::MiddleClick << Effect::LoadInSelf;
+ QTest::newRow("OverridePopup") << Decision::ReturnSelf << Cause::TargetBlank << Effect::LoadInSelf;
+ QTest::newRow("OverrideIntent") << Decision::ReturnSelf << Cause::MiddleClick << Effect::LoadInSelf;
+ QTest::newRow("AcceptPopup") << Decision::ReturnOther << Cause::TargetBlank << Effect::LoadInOther;
+ QTest::newRow("AcceptIntent") << Decision::ReturnOther << Cause::MiddleClick << Effect::LoadInOther;
+}
+
+void tst_QWebEnginePage::openLinkInNewPage()
+{
+ using Decision = OpenLinkInNewPageDecision;
+ using Cause = OpenLinkInNewPageCause;
+ using Effect = OpenLinkInNewPageEffect;
+
+ class Page : public QWebEnginePage
+ {
+ public:
+ Page *targetPage = nullptr;
+ QSignalSpy spy{this, &QWebEnginePage::loadFinished};
+ Page(QWebEngineProfile *profile) : QWebEnginePage(profile) {}
+ private:
+ QWebEnginePage *createWindow(WebWindowType) override { return targetPage; }
+ };
+
+ class View : public QWebEngineView
+ {
+ public:
+ View(Page *page)
+ {
+ resize(500, 500);
+ setPage(page);
+ }
+ };
+
+ QFETCH(Decision, decision);
+ QFETCH(Cause, cause);
+ QFETCH(Effect, effect);
+
+ QWebEngineProfile profile;
+ Page page1(&profile);
+ Page page2(&profile);
+ View view1(&page1);
+ View view2(&page2);
+
+ view1.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view1));
+
+ page1.setHtml("<html><body>"
+ "<a id='link' href='data:,hello' target='_blank'>link</a>"
+ "</body></html>");
+ QTRY_COMPARE(page1.spy.count(), 1);
+ QVERIFY(page1.spy.takeFirst().value(0).toBool());
+
+ switch (decision) {
+ case Decision::ReturnNull:
+ page1.targetPage = nullptr;
+ break;
+ case Decision::ReturnSelf:
+ page1.targetPage = &page1;
+ break;
+ case Decision::ReturnOther:
+ page1.targetPage = &page2;
+ break;
+ }
+
+ Qt::MouseButton button;
+ switch (cause) {
+ case Cause::TargetBlank:
+ button = Qt::LeftButton;
+ break;
+ case Cause::MiddleClick:
+ button = Qt::MiddleButton;
+ break;
+ }
+ QTest::mouseClick(view1.focusProxy(), button, {}, elementCenter(&page1, "link"));
+
+ switch (effect) {
+ case Effect::Blocked:
+ // Nothing to test
+ break;
+ case Effect::LoadInSelf:
+ QTRY_COMPARE(page1.spy.count(), 1);
+ QVERIFY(page1.spy.takeFirst().value(0).toBool());
+ QCOMPARE(page2.spy.count(), 0);
+ if (decision == Decision::ReturnSelf && cause == Cause::TargetBlank)
+ // History was discarded due to AddNewContents
+ QCOMPARE(page1.history()->count(), 1);
+ else
+ QCOMPARE(page1.history()->count(), 2);
+ QCOMPARE(page2.history()->count(), 0);
+ break;
+ case Effect::LoadInOther:
+ QTRY_COMPARE(page2.spy.count(), 1);
+ QVERIFY(page2.spy.takeFirst().value(0).toBool());
+ QCOMPARE(page1.spy.count(), 0);
+ QCOMPARE(page1.history()->count(), 1);
+ QCOMPARE(page2.history()->count(), 1);
+ break;
+ }
+}
+
void tst_QWebEnginePage::triggerActionWithoutMenu()
{
// Calling triggerAction should not crash even when for
@@ -3455,6 +3615,18 @@ void tst_QWebEnginePage::notificationRequest()
QCOMPARE(page.getPermission(), permission);
}
+void tst_QWebEnginePage::notificationPermission()
+{
+ QWebEngineProfile otr;
+ QWebEnginePage page(&otr, nullptr);
+ QSignalSpy spy(&page, &QWebEnginePage::loadFinished);
+ page.setHtml(QString("<html><body>Test</body></html>"), QUrl("https://www.example.com"));
+ 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"));
+}
+
void tst_QWebEnginePage::sendNotification()
{
NotificationPage page(QWebEnginePage::PermissionGrantedByUser);
@@ -4432,6 +4604,24 @@ void tst_QWebEnginePage::backgroundColor()
QTRY_COMPARE(view.grab().toImage().pixelColor(center), Qt::green);
}
+void tst_QWebEnginePage::audioMuted()
+{
+ QWebEngineProfile profile;
+ QWebEnginePage page(&profile);
+ QSignalSpy spy(&page, &QWebEnginePage::audioMutedChanged);
+
+ QCOMPARE(page.isAudioMuted(), false);
+ page.setAudioMuted(true);
+ loadSync(&page, QUrl("about:blank"));
+ QCOMPARE(page.isAudioMuted(), true);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy[0][0], QVariant(true));
+ page.setAudioMuted(false);
+ QCOMPARE(page.isAudioMuted(), false);
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(spy[1][0], QVariant(false));
+}
+
static QByteArrayList params = {QByteArrayLiteral("--use-fake-device-for-media-stream")};
W_QTEST_MAIN(tst_QWebEnginePage, params)
diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
index 6350c8510..00d4bae5a 100644
--- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
+++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
@@ -222,18 +222,6 @@ private:
}
};
-static bool loadSync(QWebEnginePage *page, const QUrl &url, bool ok = true)
-{
- QSignalSpy spy(page, &QWebEnginePage::loadFinished);
- page->load(url);
- return (!spy.empty() || spy.wait(20000)) && (spy.front().value(0).toBool() == ok);
-}
-
-static bool loadSync(QWebEngineView *view, const QUrl &url, bool ok = true)
-{
- return loadSync(view->page(), url, ok);
-}
-
void tst_QWebEngineProfile::clearDataFromCache()
{
TestServer server;
@@ -258,7 +246,7 @@ void tst_QWebEngineProfile::clearDataFromCache()
QTest::qWait(1000);
QVERIFY(sizeBeforeClear > totalSize(cacheDir));
- QVERIFY(server.stop());
+ (void)server.stop();
}
void tst_QWebEngineProfile::disableCache()
@@ -283,7 +271,7 @@ void tst_QWebEngineProfile::disableCache()
QVERIFY(loadSync(&page, server.url("/hedgehog.html")));
QVERIFY(cacheDir.exists("Cache"));
- QVERIFY(server.stop());
+ (void)server.stop();
}
class RedirectingUrlSchemeHandler : public QWebEngineUrlSchemeHandler
@@ -876,7 +864,7 @@ void tst_QWebEngineProfile::changePersistentPath()
QVERIFY(loadSync(&page, server.url("/hedgehog.html")));
QVERIFY(dataDir2.exists());
- QVERIFY(server.stop());
+ (void)server.stop();
}
void tst_QWebEngineProfile::changeHttpUserAgent()
@@ -949,7 +937,7 @@ void tst_QWebEngineProfile::changeUseForGlobalCertificateVerification()
page.reset(new QWebEnginePage(&profile));
QVERIFY(loadSync(page.get(), server.url("/hedgehog.html")));
// Don't check for error: there can be disconnects during GET hedgehog.png.
- server.stop();
+ (void)server.stop();
}
void tst_QWebEngineProfile::changePersistentCookiesPolicy()
@@ -973,7 +961,7 @@ void tst_QWebEngineProfile::changePersistentCookiesPolicy()
QVERIFY(loadSync(&page, server.url("/hedgehog.html")));
QVERIFY(dataDir.exists("Cookies"));
- QVERIFY(server.stop());
+ (void)server.stop();
}
class InitiatorSpy : public QWebEngineUrlSchemeHandler
diff --git a/tests/auto/widgets/util.h b/tests/auto/widgets/util.h
index ca03c5833..cb58f4243 100644
--- a/tests/auto/widgets/util.h
+++ b/tests/auto/widgets/util.h
@@ -36,6 +36,7 @@
#include <QSignalSpy>
#include <QTimer>
#include <qwebenginepage.h>
+#include <qwebengineview.h>
#if !defined(TESTS_SOURCE_DIR)
#define TESTS_SOURCE_DIR ""
@@ -160,6 +161,18 @@ static inline QUrl baseUrlSync(QWebEnginePage *page)
return spy.waitForResult().toUrl();
}
+static inline bool loadSync(QWebEnginePage *page, const QUrl &url, bool ok = true)
+{
+ QSignalSpy spy(page, &QWebEnginePage::loadFinished);
+ page->load(url);
+ return (!spy.empty() || spy.wait(20000)) && (spy.front().value(0).toBool() == ok);
+}
+
+static inline bool loadSync(QWebEngineView *view, const QUrl &url, bool ok = true)
+{
+ return loadSync(view->page(), url, ok);
+}
+
#define W_QSKIP(a, b) QSKIP(a)
#define W_QTEST_MAIN(TestObject, params) \