summaryrefslogtreecommitdiffstats
path: root/tests/auto/core
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-06-14 16:11:54 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-06-16 16:42:22 +0000
commit551b83b280bf83137e0c8ceefad59558bfe9e03e (patch)
treea3133e21416d599db2a635c9bbfec9b560516de7 /tests/auto/core
parent5f4fb14cb0f6b443885e79516f450853e44f650d (diff)
Stop using Widgets in WebEngineCore tests
With QWebEnginePage in Core we can now make the core tests core-only. Add the same times moves tests from widgets that only uses core classes. Change-Id: I67a25b534912d9a0891e16b0419f0db9bf434e92 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu> (cherry picked from commit b8c48ee53009365a39d9dde1f6773048ec5ee4a0) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'tests/auto/core')
-rw-r--r--tests/auto/core/CMakeLists.txt6
-rw-r--r--tests/auto/core/certificateerror/CMakeLists.txt23
-rw-r--r--tests/auto/core/certificateerror/certificateerror.pro3
-rw-r--r--tests/auto/core/certificateerror/resources/server.key27
-rw-r--r--tests/auto/core/certificateerror/resources/server.pem41
-rw-r--r--tests/auto/core/certificateerror/tst_certificateerror.cpp136
-rw-r--r--tests/auto/core/core.pro7
-rw-r--r--tests/auto/core/devtools/CMakeLists.txt7
-rw-r--r--tests/auto/core/devtools/devtools.pro1
-rw-r--r--tests/auto/core/devtools/tst_devtools.cpp87
-rw-r--r--tests/auto/core/origins/CMakeLists.txt45
-rw-r--r--tests/auto/core/origins/origins.pro8
-rw-r--r--tests/auto/core/origins/resources/createObjectURL.html11
-rw-r--r--tests/auto/core/origins/resources/dedicatedWorker.html19
-rw-r--r--tests/auto/core/origins/resources/dedicatedWorker.js1
-rw-r--r--tests/auto/core/origins/resources/mixedSchemes.html31
-rw-r--r--tests/auto/core/origins/resources/mixedSchemesWithCsp.html32
-rw-r--r--tests/auto/core/origins/resources/mixedSchemes_frame.html11
-rw-r--r--tests/auto/core/origins/resources/mixedXHR.html19
-rw-r--r--tests/auto/core/origins/resources/mixedXHR.txt1
-rw-r--r--tests/auto/core/origins/resources/redirect.css8
-rw-r--r--tests/auto/core/origins/resources/redirect.html10
-rw-r--r--tests/auto/core/origins/resources/serviceWorker.html18
-rw-r--r--tests/auto/core/origins/resources/serviceWorker.js1
-rw-r--r--tests/auto/core/origins/resources/sharedWorker.html19
-rw-r--r--tests/auto/core/origins/resources/sharedWorker.js6
-rw-r--r--tests/auto/core/origins/resources/subdir/frame2.html10
-rw-r--r--tests/auto/core/origins/resources/subdir/index.html26
-rw-r--r--tests/auto/core/origins/resources/subdir_frame1.html10
-rw-r--r--tests/auto/core/origins/resources/viewSource.html9
-rw-r--r--tests/auto/core/origins/resources/websocket.html23
-rw-r--r--tests/auto/core/origins/tst_origins.cpp958
-rw-r--r--tests/auto/core/origins/tst_origins.qrc22
-rw-r--r--tests/auto/core/qwebenginecookiestore/CMakeLists.txt2
-rw-r--r--tests/auto/core/qwebenginesettings/BLACKLIST2
-rw-r--r--tests/auto/core/qwebenginesettings/CMakeLists.txt9
-rw-r--r--tests/auto/core/qwebenginesettings/qwebenginesettings.pro2
-rw-r--r--tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp198
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt2
-rw-r--r--tests/auto/core/tests.pri2
40 files changed, 1848 insertions, 5 deletions
diff --git a/tests/auto/core/CMakeLists.txt b/tests/auto/core/CMakeLists.txt
index ee2f010d0..0d2340188 100644
--- a/tests/auto/core/CMakeLists.txt
+++ b/tests/auto/core/CMakeLists.txt
@@ -1,5 +1,11 @@
add_subdirectory(qwebenginecookiestore)
+add_subdirectory(qwebenginesettings)
add_subdirectory(qwebengineurlrequestinterceptor)
+add_subdirectory(origins)
+if(NOT boot2qt)
+ add_subdirectory(devtools)
+endif()
if(QT_FEATURE_ssl)
add_subdirectory(qwebengineclientcertificatestore)
+ add_subdirectory(certificateerror)
endif()
diff --git a/tests/auto/core/certificateerror/CMakeLists.txt b/tests/auto/core/certificateerror/CMakeLists.txt
new file mode 100644
index 000000000..57801e195
--- /dev/null
+++ b/tests/auto/core/certificateerror/CMakeLists.txt
@@ -0,0 +1,23 @@
+include(../../httpserver/httpserver.cmake)
+include(../../util/util.cmake)
+
+qt_internal_add_test(tst_certificateerror
+ SOURCES
+ tst_certificateerror.cpp
+ LIBRARIES
+ Qt::WebEngineCore
+ Test::HttpServer
+ Test::Util
+)
+
+set(tst_certificateerror_resource_files
+ "resources/server.pem"
+ "resources/server.key"
+)
+
+qt_internal_add_resource(tst_certificateerror "tst_certificateerror"
+ PREFIX
+ "/"
+ FILES
+ ${tst_certificateerror_resource_files}
+)
diff --git a/tests/auto/core/certificateerror/certificateerror.pro b/tests/auto/core/certificateerror/certificateerror.pro
new file mode 100644
index 000000000..73ba7515b
--- /dev/null
+++ b/tests/auto/core/certificateerror/certificateerror.pro
@@ -0,0 +1,3 @@
+include(../tests.pri)
+include(../../shared/https.pri)
+QT *= core-private
diff --git a/tests/auto/core/certificateerror/resources/server.key b/tests/auto/core/certificateerror/resources/server.key
new file mode 100644
index 000000000..9bf87aee3
--- /dev/null
+++ b/tests/auto/core/certificateerror/resources/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAqAygFPG5ILLb3G51D0OIN4Kpm5t3Oh1nByTnvi1kMz+sCBBd
+CSugt4NnKkB6kiGtMEsrEm1/xg8Bkfbpet3v3+jAidRpjvCISqy3Z9D1cgCFM46h
+iob/AvLZpqITiAgsU4fJ4auuIKhFplIGrIKMv2gK8haoBGBoRUD1RM+irwjEr6TN
+XTQt2Ap+Ouxs53NLPhAOgumpfzzRR8/Umbhen+G5MhH+XTzzreiClz2V6A79ePJj
+y1uQ8NJ79feOOWBDRizRDWwxsnNd24GjkpvcaTwafiK6Vdqeub+XTtiB5RPal2on
+Cj0TQDcnaacecl/zmUWsIFNkNJWDcd3/vEdyOQIDAQABAoIBAQCW93icOCdim6tu
+FIDu7HEjxSsPUpPCToWu4lWaAHcinxGx0NlzkpD4K4DzcSdrvfszBmQ0UtBVokd7
+1IAdU+HZmePWLk+CDM2zoAPHrO3Cs3r2PS0cIHhZMsearcG0E/uWMseHB08PoXuo
+lcnPEhzVGueyYe4guGcTx+5PGeUBLf+fJcEc3rIQnT2LYulM2aqBZSQM3jRUaPYs
+F0awDpCNwajW/Bt2VB14Pr+H5MJ+WSznFCqW7SolBkqDGfKckXPSHgX6xZ0y7VCI
+MM8vwlVI4mPkaHvSQMSI8vS4Qh+SGQCSs/AuuNLjjPoz1YotV3Ih4YbLj6BjFP2g
+CrqzT6VNAoGBANOHmsqE0nRkLzonTDrMdla5b0TjTxwtNM5DjLgJa6UBBqPe+1Lv
+JFoBP9bIfYDRWZOZrxXItfMmM43nK/ST6Xqgx1IpHUCLKVr2pA9RXrP+m4oawfgn
+frW212fHibeOYiLy+DaQXQ0VRFxsc/VbwKVyVlMEcNg3N93x2E67M7vjAoGBAMtg
+7wDa+5gjwuyNr7LKkp5VDTmtKQhoDtg4sw6MSQSMF6fJT9Z4kGTZ23+G85/LsM/k
+iXbceabGJ0CQJvGn6oW4dI2Ut2c2nCNVbQCxJ6Nyn/yW7bRLShMnwXvbGAVxVUax
+5ohJPZGJ8ar2CP76A0bkvm2Nwylq2gp6Y8h7+iwzAoGBAKizwfQ6sk45iKDsrpNG
+dir8gY2DbJigRTksDpLIkJ1skAspz295YpiV3oBCLjYKwVJCg6zwAo0FrqBB+oB5
+ZwByMgWI3NeZJUZy5q2Ay/Lp4MroRELR3PC3/lu6fE90szgEZ4m84TmJ+Jdtt527
+q41H/yj+pbELePb95vIDw2LZAoGBAJBZ+MmupCzUFSI5Xp+UUIS48W4ijaE92mt1
+swF8aMcleBTLOjOL11D9oGHfs0OUG6czGq6WxnGs62dT6ZBUEo1e4rsq9xH3HNOn
+anq3Qt8sGIn7xjPVzHnUGeyDEYWrb0+CLZJGCcEnG7SwdKolYfYLnW281Oysvp35
+SKGf/W0pAoGAa2+sZmhb1mpGAf6Bi4z+uym/6qOJmG6CnrBSM9e/r8nujwFVkCYF
+3iz48qx3GbuliO6za8aM1drX2u8KWp1uP5KzwYvtW5SfpQ1eusFblHEYQQNRcKLT
+j/wZBXnU961eMKkkTe2XsPirO8rVhVmxuFLqT/aEPffcragQFFIGOEQ=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/core/certificateerror/resources/server.pem b/tests/auto/core/certificateerror/resources/server.pem
new file mode 100644
index 000000000..a201ed08e
--- /dev/null
+++ b/tests/auto/core/certificateerror/resources/server.pem
@@ -0,0 +1,41 @@
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIUFZEIIzeR7lEA10rb14w7MfhP87MwDQYJKoZIhvcNAQEL
+BQAwWjELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0GA1UEBwwGQmVy
+bGluMRUwEwYDVQQKDAxUaGVRdENvbXBhbnkxEjAQBgNVBAsMCXdlYmVuZ2luZTAe
+Fw0yMTA1MTAyMTM1MTJaFw0yMjA1MTAyMTM1MTJaMGAxCzAJBgNVBAYTAkRFMQ8w
+DQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJlcmxpbjEVMBMGA1UECgwMVGhlUXRD
+b21wYW55MRgwFgYDVQQDDA93ZWJlbmdpbmUucXQuaW8wggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCoDKAU8bkgstvcbnUPQ4g3gqmbm3c6HWcHJOe+LWQz
+P6wIEF0JK6C3g2cqQHqSIa0wSysSbX/GDwGR9ul63e/f6MCJ1GmO8IhKrLdn0PVy
+AIUzjqGKhv8C8tmmohOICCxTh8nhq64gqEWmUgasgoy/aAryFqgEYGhFQPVEz6Kv
+CMSvpM1dNC3YCn467Gznc0s+EA6C6al/PNFHz9SZuF6f4bkyEf5dPPOt6IKXPZXo
+Dv148mPLW5Dw0nv19445YENGLNENbDGyc13bgaOSm9xpPBp+IrpV2p65v5dO2IHl
+E9qXaicKPRNANydppx5yX/OZRawgU2Q0lYNx3f+8R3I5AgMBAAGjMzAxMBoGA1Ud
+EQQTMBGCD3dlYmVuZ2luZS5xdC5pbzATBgNVHSUEDDAKBggrBgEFBQcDATANBgkq
+hkiG9w0BAQsFAAOCAQEAjThKpP0sBv1vEmaqBc1wTu//7RHmFcoStTt3scADzb2C
+9gjOVC4NzxBneLkv01444Z1p/Iiu/ZZ+VKu7aJElJgnBWEisYwJ09t3cdZRA0UY7
+XRvTVAqV0OlsB1Jn0afE+aTLGjWo+jSYzua0O+NK74e23p9jkdSmXxH9w0FB/oyM
+FGIOFnnfP0+QR4ZVvAGk2H60tBHQKmCM6b87TiD4GQIfOghCQWH+qJYSuyGu4hkE
+uis+n1KHHhed3GIJOHpm7gt1C9qtjcp1nOpv0ycQjfc9CGvr02BcQjhMeO65hX0A
+TvCgKN9/XMFv5jwwjjPCL12GBhwnN2k9hM/tEYpe2A==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDOzCCAiMCFDwWg4NZxCplj3qyBxAUTi1wmj4jMA0GCSqGSIb3DQEBCwUAMFox
+CzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJlcmxpbjEV
+MBMGA1UECgwMVGhlUXRDb21wYW55MRIwEAYDVQQLDAl3ZWJlbmdpbmUwHhcNMjEw
+NTEwMjEzMTE4WhcNMjIwNTEwMjEzMTE4WjBaMQswCQYDVQQGEwJERTEPMA0GA1UE
+CAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xFTATBgNVBAoMDFRoZVF0Q29tcGFu
+eTESMBAGA1UECwwJd2ViZW5naW5lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAuc/8xVrfSzOsI6kYul+o1QIPBh1I86eQm1PhTBDMAAPHuzyPaEMgBkn2
+XAUmvkynGpNioaJDU2ndV2fBHvsoeQCdNNmjFTe1rKYjrN6U2X5KoYSzN93TOYzK
+aR38fEFx+w4qV76nnxSjYtGNe9z74GrfWFMdDQ0NJKzvaO4gaZ+OOg0OzWy4MJQ0
+aINo3UV55Y7Nt92AxFweiuHucKu+rjf3BX7n0Af/Tcs2c84f0R3HA7euReSibVvX
+f33eHLRKwu2bvDjXiUzOdkxBn9GTo6Q09LyY6wDG0ZdWnyCKj3NBQKBVrq+bs3Q0
+ATsWhj/PvYlZhhZh4EOlqYOhCpwv4wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCC
+pLSFGJcG0zhHW+2A6ogmpn2tA8gKUZx7f0J1nwgPEoAXQqWQv/299ZtmWfMKHUkk
+ygG4u80C87wWPH42XWXo/KDrP9iYzoqAvtqbRuPG9PAxefQ/JUSnuhikA51g9+Mu
+IDKKKSI+y/JW9u0Qo77fp/5n2DaFn5B+pBYvn/xLfaEa9bRdJMTEMsElGbPBzMZd
+I/7X6B78X6Ow5TuRKSeZA7E1AZ/+e5A4Hj65bLAugoSKz3zaS0dV26LwAo18c2zP
+TqtwHyIVj4QCoI6Z694q9KH4Pkml3fz8VSkk+MvZMWapvUhHu/DneTgqGbp9POYg
+nx6oWME6idhnvN6DljxB
+-----END CERTIFICATE-----
diff --git a/tests/auto/core/certificateerror/tst_certificateerror.cpp b/tests/auto/core/certificateerror/tst_certificateerror.cpp
new file mode 100644
index 000000000..74c7e3bd4
--- /dev/null
+++ b/tests/auto/core/certificateerror/tst_certificateerror.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+#include <httpsserver.h>
+#include <util.h>
+
+#include <QWebEngineCertificateError>
+#include <QWebEnginePage>
+#include <QWebEngineProfile>
+#include <QWebEngineSettings>
+
+#include <QtTest/QtTest>
+
+class tst_CertificateError : public QObject
+{
+ Q_OBJECT
+public:
+ tst_CertificateError() { }
+
+private Q_SLOTS:
+ void handleError_data();
+ void handleError();
+};
+
+struct PageWithCertificateErrorHandler : QWebEnginePage
+{
+ Q_OBJECT
+
+public:
+ PageWithCertificateErrorHandler(bool defer, bool accept, QObject *p = nullptr)
+ : QWebEnginePage(p), deferError(defer), acceptCertificate(accept)
+ , loadSpy(this, &QWebEnginePage::loadFinished)
+ {
+ connect(this, &PageWithCertificateErrorHandler::certificateError,
+ this, &PageWithCertificateErrorHandler::onCertificateError);
+ }
+
+ bool deferError, acceptCertificate;
+
+ QSignalSpy loadSpy;
+ QScopedPointer<QWebEngineCertificateError> error;
+
+public Q_SLOTS:
+ void onCertificateError(QWebEngineCertificateError e)
+ {
+ error.reset(new QWebEngineCertificateError(e));
+ if (deferError) {
+ error->defer();
+ return;
+ }
+
+ if (acceptCertificate)
+ error->acceptCertificate();
+ else
+ error->rejectCertificate();
+ }
+};
+
+void tst_CertificateError::handleError_data()
+{
+ QTest::addColumn<bool>("deferError");
+ QTest::addColumn<bool>("acceptCertificate");
+ QTest::addColumn<QString>("expectedContent");
+ QTest::addRow("Reject") << false << false << QString();
+ QTest::addRow("DeferReject") << true << false << QString();
+ QTest::addRow("DeferAccept") << true << true << "TEST";
+}
+
+void tst_CertificateError::handleError()
+{
+ HttpsServer server(":/resources/server.pem",":/resources/server.key");
+ server.setExpectError(true);
+ QVERIFY(server.start());
+
+ connect(&server, &HttpsServer::newRequest, [&] (HttpReqRep *rr) {
+ rr->setResponseBody(QByteArrayLiteral("<html><body>TEST</body></html>"));
+ rr->sendResponse();
+ });
+
+ QFETCH(bool, deferError);
+ QFETCH(bool, acceptCertificate);
+ QFETCH(QString, expectedContent);
+
+ PageWithCertificateErrorHandler page(deferError, acceptCertificate);
+ page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+
+ page.setUrl(server.url());
+ QTRY_VERIFY(page.error);
+ QVERIFY(page.error->isOverridable());
+ auto chain = page.error->certificateChain();
+ QCOMPARE(chain.size(), 2);
+ QCOMPARE(chain[0].serialNumber(), "15:91:08:23:37:91:ee:51:00:d7:4a:db:d7:8c:3b:31:f8:4f:f3:b3");
+ QCOMPARE(chain[1].serialNumber(), "3c:16:83:83:59:c4:2a:65:8f:7a:b2:07:10:14:4e:2d:70:9a:3e:23");
+
+ if (deferError) {
+ QCOMPARE(page.loadSpy.count(), 0);
+ QCOMPARE(toPlainTextSync(&page), QString());
+
+ if (acceptCertificate)
+ page.error->acceptCertificate();
+ else
+ page.error->rejectCertificate();
+
+ page.error.reset();
+ }
+ QTRY_COMPARE_WITH_TIMEOUT(page.loadSpy.count(), 1, 30000);
+ QCOMPARE(page.loadSpy.takeFirst().value(0).toBool(), acceptCertificate);
+ QCOMPARE(toPlainTextSync(&page), expectedContent);
+}
+
+QTEST_MAIN(tst_CertificateError)
+#include <tst_certificateerror.moc>
diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro
index 1dc5e052c..23b25bd97 100644
--- a/tests/auto/core/core.pro
+++ b/tests/auto/core/core.pro
@@ -3,7 +3,10 @@ QT_FOR_CONFIG += network-private
SUBDIRS += \
qwebenginecookiestore \
- qwebengineurlrequestinterceptor
+ qwebenginesettings \
+ qwebengineurlrequestinterceptor \
+ devtools \
+ origins
-qtConfig(ssl): SUBDIRS += qwebengineclientcertificatestore
+qtConfig(ssl): SUBDIRS += certificateerror qwebengineclientcertificatestore
diff --git a/tests/auto/core/devtools/CMakeLists.txt b/tests/auto/core/devtools/CMakeLists.txt
new file mode 100644
index 000000000..fd8d850f0
--- /dev/null
+++ b/tests/auto/core/devtools/CMakeLists.txt
@@ -0,0 +1,7 @@
+qt_internal_add_test(tst_devtools
+ SOURCES
+ tst_devtools.cpp
+ LIBRARIES
+ Qt::WebEngineCore
+)
+
diff --git a/tests/auto/core/devtools/devtools.pro b/tests/auto/core/devtools/devtools.pro
new file mode 100644
index 000000000..e99c7f493
--- /dev/null
+++ b/tests/auto/core/devtools/devtools.pro
@@ -0,0 +1 @@
+include(../tests.pri)
diff --git a/tests/auto/core/devtools/tst_devtools.cpp b/tests/auto/core/devtools/tst_devtools.cpp
new file mode 100644
index 000000000..3026b3931
--- /dev/null
+++ b/tests/auto/core/devtools/tst_devtools.cpp
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include <qwebenginepage.h>
+
+class tst_DevTools : public QObject {
+ Q_OBJECT
+
+private Q_SLOTS:
+ void attachAndDestroyPageFirst();
+ void attachAndDestroyInspectorFirst();
+};
+
+void tst_DevTools::attachAndDestroyPageFirst()
+{
+ // External inspector + manual destruction of page first
+ QWebEnginePage* page = new QWebEnginePage();
+ QWebEnginePage* inspector = new QWebEnginePage();
+
+ QSignalSpy spy(page, &QWebEnginePage::loadFinished);
+ page->load(QUrl("data:text/plain,foobarbaz"));
+ QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 12000);
+
+ inspector->setInspectedPage(page);
+ page->triggerAction(QWebEnginePage::InspectElement);
+
+ // This is deliberately racy:
+ QTest::qWait(10);
+
+ delete page;
+ delete inspector;
+}
+
+void tst_DevTools::attachAndDestroyInspectorFirst()
+{
+ // External inspector + manual destruction of inspector first
+ QWebEnginePage* page = new QWebEnginePage();
+ QWebEnginePage* inspector = new QWebEnginePage();
+ inspector->setInspectedPage(page);
+
+ QSignalSpy spy(page, &QWebEnginePage::loadFinished);
+ page->setHtml(QStringLiteral("<body><h1>FOO BAR!</h1></body>"));
+ QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 12000);
+
+ page->triggerAction(QWebEnginePage::InspectElement);
+
+ delete inspector;
+
+ page->triggerAction(QWebEnginePage::InspectElement);
+
+ // This is deliberately racy:
+ QTest::qWait(10);
+
+ delete page;
+}
+
+
+QTEST_MAIN(tst_DevTools)
+
+#include "tst_devtools.moc"
diff --git a/tests/auto/core/origins/CMakeLists.txt b/tests/auto/core/origins/CMakeLists.txt
new file mode 100644
index 000000000..a044ea2ef
--- /dev/null
+++ b/tests/auto/core/origins/CMakeLists.txt
@@ -0,0 +1,45 @@
+include(../../httpserver/httpserver.cmake)
+include(../../util/util.cmake)
+
+qt_internal_add_test(tst_origins
+ SOURCES
+ tst_origins.cpp
+ LIBRARIES
+ Qt::WebEngineCore
+ Test::HttpServer
+ Test::Util
+)
+
+set(tst_origins_resource_files
+ "resources/createObjectURL.html"
+ "resources/dedicatedWorker.html"
+ "resources/dedicatedWorker.js"
+ "resources/mixedSchemes.html"
+ "resources/mixedSchemesWithCsp.html"
+ "resources/mixedSchemes_frame.html"
+ "resources/mixedXHR.html"
+ "resources/mixedXHR.txt"
+ "resources/serviceWorker.html"
+ "resources/serviceWorker.js"
+ "resources/sharedWorker.html"
+ "resources/sharedWorker.js"
+ "resources/subdir/frame2.html"
+ "resources/subdir/index.html"
+ "resources/subdir_frame1.html"
+ "resources/viewSource.html"
+ "resources/websocket.html"
+)
+
+qt_internal_add_resource(tst_origins "tst_origins"
+ PREFIX
+ "/"
+ FILES
+ ${tst_origins_resource_files}
+)
+
+qt_internal_extend_target(tst_origins CONDITION QT_FEATURE_webengine_webchannel AND TARGET Qt::WebSockets
+ DEFINES
+ WEBSOCKETS
+ LIBRARIES
+ Qt::WebSockets
+)
diff --git a/tests/auto/core/origins/origins.pro b/tests/auto/core/origins/origins.pro
new file mode 100644
index 000000000..6cf0b2b92
--- /dev/null
+++ b/tests/auto/core/origins/origins.pro
@@ -0,0 +1,8 @@
+include(../tests.pri)
+include(../../shared/http.pri)
+
+qtConfig(webengine-webchannel):qtHaveModule(websockets) {
+ QT += websockets
+ DEFINES += WEBSOCKETS
+}
+
diff --git a/tests/auto/core/origins/resources/createObjectURL.html b/tests/auto/core/origins/resources/createObjectURL.html
new file mode 100644
index 000000000..133f636bb
--- /dev/null
+++ b/tests/auto/core/origins/resources/createObjectURL.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>createObjectURL</title>
+ <script>
+ const blob = new Blob(['foo']);
+ const result = URL.createObjectURL(blob);
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/core/origins/resources/dedicatedWorker.html b/tests/auto/core/origins/resources/dedicatedWorker.html
new file mode 100644
index 000000000..cb4f14e73
--- /dev/null
+++ b/tests/auto/core/origins/resources/dedicatedWorker.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicatedWorker</title>
+ <script>
+ var done = false;
+ var result;
+ var error;
+ try {
+ let worker = new Worker("dedicatedWorker.js");
+ worker.onmessage = (e) => { done = true; result = e.data; };
+ worker.postMessage(41);
+ } catch (e) {
+ done = true; error = e.message;
+ }
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/core/origins/resources/dedicatedWorker.js b/tests/auto/core/origins/resources/dedicatedWorker.js
new file mode 100644
index 000000000..2631939d7
--- /dev/null
+++ b/tests/auto/core/origins/resources/dedicatedWorker.js
@@ -0,0 +1 @@
+onmessage = (e) => { postMessage(e.data + 1); };
diff --git a/tests/auto/core/origins/resources/mixedSchemes.html b/tests/auto/core/origins/resources/mixedSchemes.html
new file mode 100644
index 000000000..c73e9ecdc
--- /dev/null
+++ b/tests/auto/core/origins/resources/mixedSchemes.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Mixed</title>
+ <script>
+ var result;
+ var canary;
+
+ function setIFrameUrl(url) {
+ result = undefined;
+ canary = undefined;
+ document.getElementById("iframe").setAttribute("src", url);
+ // Early fire is OK unless the test is expecting cannotLoad.
+ // If timeout is too short then a false positive is possible.
+ setTimeout(() => { result = result || "cannotLoad"; }, 500);
+ }
+
+ addEventListener("load", function() {
+ document.getElementById("iframe").addEventListener("load", function() {
+ if (canary && window[0].canary)
+ result = "canLoadAndAccess";
+ else
+ result = "canLoadButNotAccess";
+ });
+ });
+ </script>
+ </head>
+ <body>
+ <iframe id="iframe"></iframe>
+ </body>
+</html>
diff --git a/tests/auto/core/origins/resources/mixedSchemesWithCsp.html b/tests/auto/core/origins/resources/mixedSchemesWithCsp.html
new file mode 100644
index 000000000..ad7cbeeb7
--- /dev/null
+++ b/tests/auto/core/origins/resources/mixedSchemesWithCsp.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta http-equiv="Content-Security-Policy" content="frame-src 'none'">
+ <title>Mixed</title>
+ <script>
+ var result;
+ var canary;
+
+ function setIFrameUrl(url) {
+ result = undefined;
+ canary = undefined;
+ document.getElementById("iframe").setAttribute("src", url);
+ // Early fire is OK unless the test is expecting cannotLoad.
+ // If timeout is too short then a false positive is possible.
+ setTimeout(() => { result = result || "cannotLoad"; }, 500);
+ }
+
+ addEventListener("load", function() {
+ document.getElementById("iframe").addEventListener("load", function() {
+ if (canary && window[0].canary)
+ result = "canLoadAndAccess";
+ else
+ result = "canLoadButNotAccess";
+ });
+ });
+ </script>
+ </head>
+ <body>
+ <iframe id="iframe"></iframe>
+ </body>
+</html>
diff --git a/tests/auto/core/origins/resources/mixedSchemes_frame.html b/tests/auto/core/origins/resources/mixedSchemes_frame.html
new file mode 100644
index 000000000..00c20ba37
--- /dev/null
+++ b/tests/auto/core/origins/resources/mixedSchemes_frame.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Mixed - Frame</title>
+ <script>
+ var canary = true;
+ parent.canary = true;
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/core/origins/resources/mixedXHR.html b/tests/auto/core/origins/resources/mixedXHR.html
new file mode 100644
index 000000000..3dfd90006
--- /dev/null
+++ b/tests/auto/core/origins/resources/mixedXHR.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Mixed</title>
+ <script>
+ var result;
+ function sendXHR(url) {
+ result = undefined;
+ let req = new XMLHttpRequest();
+ req.addEventListener("load", () => { result = req.responseText });
+ req.addEventListener("error", () => { result = "error"; });
+ req.open("GET", url);
+ req.send();
+ }
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/tests/auto/core/origins/resources/mixedXHR.txt b/tests/auto/core/origins/resources/mixedXHR.txt
new file mode 100644
index 000000000..b5754e203
--- /dev/null
+++ b/tests/auto/core/origins/resources/mixedXHR.txt
@@ -0,0 +1 @@
+ok \ No newline at end of file
diff --git a/tests/auto/core/origins/resources/redirect.css b/tests/auto/core/origins/resources/redirect.css
new file mode 100644
index 000000000..41d7560cc
--- /dev/null
+++ b/tests/auto/core/origins/resources/redirect.css
@@ -0,0 +1,8 @@
+@font-face {
+ font-family: 'MyWebFont';
+ src: url('redirect1:/resources/Akronim-Regular.woff2') format('woff2');
+}
+
+body {
+ font-family: 'MyWebFont', Fallback, sans-serif;
+}
diff --git a/tests/auto/core/origins/resources/redirect.html b/tests/auto/core/origins/resources/redirect.html
new file mode 100644
index 000000000..04948e14b
--- /dev/null
+++ b/tests/auto/core/origins/resources/redirect.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>redirect</title>
+ <link rel="stylesheet" href="redirect1:/resources/redirect.css">
+ </head>
+ <body>
+ Text
+ </body>
+</html>
diff --git a/tests/auto/core/origins/resources/serviceWorker.html b/tests/auto/core/origins/resources/serviceWorker.html
new file mode 100644
index 000000000..27890c98f
--- /dev/null
+++ b/tests/auto/core/origins/resources/serviceWorker.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>serviceWorker</title>
+ <script>
+ var done = false;
+ var error;
+ try {
+ navigator.serviceWorker.register("serviceWorker.js")
+ .then((r) => { done = true; })
+ .catch((e) => { done = true; error = e.message; });
+ } catch (e) {
+ done = true; error = e.message;
+ }
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/core/origins/resources/serviceWorker.js b/tests/auto/core/origins/resources/serviceWorker.js
new file mode 100644
index 000000000..40a8c178f
--- /dev/null
+++ b/tests/auto/core/origins/resources/serviceWorker.js
@@ -0,0 +1 @@
+/* empty */
diff --git a/tests/auto/core/origins/resources/sharedWorker.html b/tests/auto/core/origins/resources/sharedWorker.html
new file mode 100644
index 000000000..8b5a0a794
--- /dev/null
+++ b/tests/auto/core/origins/resources/sharedWorker.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>sharedWorker</title>
+ <script>
+ var done;
+ var result;
+ var error;
+ try {
+ let worker = new SharedWorker("sharedWorker.js");
+ worker.port.onmessage = (e) => { done = true; result = e.data; };
+ worker.port.postMessage(41);
+ } catch (e) {
+ done = true; error = e.message;
+ }
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/core/origins/resources/sharedWorker.js b/tests/auto/core/origins/resources/sharedWorker.js
new file mode 100644
index 000000000..60ef93a5f
--- /dev/null
+++ b/tests/auto/core/origins/resources/sharedWorker.js
@@ -0,0 +1,6 @@
+onconnect = function(e) {
+ let port = e.ports[0];
+ port.onmessage = function(e) {
+ port.postMessage(e.data + 1);
+ };
+};
diff --git a/tests/auto/core/origins/resources/subdir/frame2.html b/tests/auto/core/origins/resources/subdir/frame2.html
new file mode 100644
index 000000000..3a2f664ca
--- /dev/null
+++ b/tests/auto/core/origins/resources/subdir/frame2.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Subdir - Frame 2</title>
+ <script>
+ parent.msg[1] = "world";
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/core/origins/resources/subdir/index.html b/tests/auto/core/origins/resources/subdir/index.html
new file mode 100644
index 000000000..9c5d5d782
--- /dev/null
+++ b/tests/auto/core/origins/resources/subdir/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Subdir</title>
+
+ <script>
+ var msg = [];
+ </script>
+
+ <!-- for manual testing -->
+ <script>
+ window.addEventListener("load", () => {
+ for (let i of [0, 1]) {
+ let p = document.createElement("p");
+ p.appendChild(document.createTextNode(`frame ${i+1} says: ${msg[i]}`));
+ document.body.insertBefore(p, null);
+ }
+ });
+ </script>
+
+ </head>
+ <body>
+ <iframe src="../subdir_frame1.html"></iframe>
+ <iframe src="frame2.html"></iframe>
+ </body>
+</html>
diff --git a/tests/auto/core/origins/resources/subdir_frame1.html b/tests/auto/core/origins/resources/subdir_frame1.html
new file mode 100644
index 000000000..63973f2f4
--- /dev/null
+++ b/tests/auto/core/origins/resources/subdir_frame1.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Subdir - Frame 1</title>
+ <script>
+ parent.msg[0] = "hello";
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/core/origins/resources/viewSource.html b/tests/auto/core/origins/resources/viewSource.html
new file mode 100644
index 000000000..977074c74
--- /dev/null
+++ b/tests/auto/core/origins/resources/viewSource.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>viewSource</title>
+ </head>
+ <body>
+ <p>viewSource</p>
+ </body>
+</html>
diff --git a/tests/auto/core/origins/resources/websocket.html b/tests/auto/core/origins/resources/websocket.html
new file mode 100644
index 000000000..31db66571
--- /dev/null
+++ b/tests/auto/core/origins/resources/websocket.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>WebSocket</title>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
+ <script>
+ var result;
+ new QWebChannel(qt.webChannelTransport, channel => {
+ const ws = new WebSocket(channel.objects.echoServer.url);
+ ws.addEventListener("open", event => {
+ ws.send("ok");
+ });
+ ws.addEventListener("message", event => {
+ result = event.data;
+ });
+ ws.addEventListener("close", event => {
+ result = event.code;
+ });
+ })
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/core/origins/tst_origins.cpp b/tests/auto/core/origins/tst_origins.cpp
new file mode 100644
index 000000000..a34404a7e
--- /dev/null
+++ b/tests/auto/core/origins/tst_origins.cpp
@@ -0,0 +1,958 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+
+#include <util.h>
+#include "httpserver.h"
+
+#include <QtCore/qfile.h>
+#include <QtTest/QtTest>
+#include <QtWebEngineCore/qwebengineurlrequestjob.h>
+#include <QtWebEngineCore/qwebengineurlscheme.h>
+#include <QtWebEngineCore/qwebengineurlschemehandler.h>
+#include <QtWebEngineCore/qwebenginesettings.h>
+#include <QtWebEngineCore/qwebengineprofile.h>
+#include <QtWebEngineCore/qwebenginepage.h>
+
+#if defined(WEBSOCKETS)
+#include <QtWebSockets/qwebsocket.h>
+#include <QtWebSockets/qwebsocketserver.h>
+#include <QtWebChannel/qwebchannel.h>
+#endif
+#include <qaction.h>
+
+#define QSL QStringLiteral
+#define QBAL QByteArrayLiteral
+
+void registerSchemes()
+{
+ {
+ QWebEngineUrlScheme scheme(QBAL("PathSyntax"));
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("PathSyntax-Secure"));
+ scheme.setFlags(QWebEngineUrlScheme::SecureScheme);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("PathSyntax-Secure-ServiceWorkersAllowed"));
+ scheme.setFlags(QWebEngineUrlScheme::SecureScheme | QWebEngineUrlScheme::ServiceWorkersAllowed);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("PathSyntax-Local"));
+ scheme.setFlags(QWebEngineUrlScheme::LocalScheme);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("PathSyntax-LocalAccessAllowed"));
+ scheme.setFlags(QWebEngineUrlScheme::LocalAccessAllowed);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("PathSyntax-NoAccessAllowed"));
+ scheme.setFlags(QWebEngineUrlScheme::NoAccessAllowed);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("PathSyntax-ServiceWorkersAllowed"));
+ scheme.setFlags(QWebEngineUrlScheme::ServiceWorkersAllowed);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("PathSyntax-ViewSourceAllowed"));
+ scheme.setFlags(QWebEngineUrlScheme::ViewSourceAllowed);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("HostSyntax"));
+ scheme.setSyntax(QWebEngineUrlScheme::Syntax::Host);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("HostSyntax-ContentSecurityPolicyIgnored"));
+ scheme.setSyntax(QWebEngineUrlScheme::Syntax::Host);
+ scheme.setFlags(QWebEngineUrlScheme::ContentSecurityPolicyIgnored);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("HostAndPortSyntax"));
+ scheme.setSyntax(QWebEngineUrlScheme::Syntax::HostAndPort);
+ scheme.setDefaultPort(42);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("HostPortAndUserInformationSyntax"));
+ scheme.setSyntax(QWebEngineUrlScheme::Syntax::HostPortAndUserInformation);
+ scheme.setDefaultPort(42);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("redirect1"));
+ scheme.setFlags(QWebEngineUrlScheme::CorsEnabled);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("redirect2"));
+ scheme.setFlags(QWebEngineUrlScheme::CorsEnabled);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+ {
+ QWebEngineUrlScheme scheme(QBAL("cors"));
+ scheme.setFlags(QWebEngineUrlScheme::CorsEnabled);
+ QWebEngineUrlScheme::registerScheme(scheme);
+ }
+
+}
+Q_CONSTRUCTOR_FUNCTION(registerSchemes)
+
+class TstUrlSchemeHandler final : public QWebEngineUrlSchemeHandler {
+ Q_OBJECT
+
+public:
+ TstUrlSchemeHandler(QWebEngineProfile *profile)
+ {
+ profile->installUrlSchemeHandler(QBAL("tst"), this);
+
+ profile->installUrlSchemeHandler(QBAL("PathSyntax"), this);
+ profile->installUrlSchemeHandler(QBAL("PathSyntax-Secure"), this);
+ profile->installUrlSchemeHandler(QBAL("PathSyntax-Secure-ServiceWorkersAllowed"), this);
+ profile->installUrlSchemeHandler(QBAL("PathSyntax-Local"), this);
+ profile->installUrlSchemeHandler(QBAL("PathSyntax-LocalAccessAllowed"), this);
+ profile->installUrlSchemeHandler(QBAL("PathSyntax-NoAccessAllowed"), this);
+ profile->installUrlSchemeHandler(QBAL("PathSyntax-ServiceWorkersAllowed"), this);
+ profile->installUrlSchemeHandler(QBAL("PathSyntax-ViewSourceAllowed"), this);
+ profile->installUrlSchemeHandler(QBAL("HostSyntax"), this);
+ profile->installUrlSchemeHandler(QBAL("HostSyntax-ContentSecurityPolicyIgnored"), this);
+ profile->installUrlSchemeHandler(QBAL("HostAndPortSyntax"), this);
+ profile->installUrlSchemeHandler(QBAL("HostPortAndUserInformationSyntax"), this);
+ profile->installUrlSchemeHandler(QBAL("redirect1"), this);
+ profile->installUrlSchemeHandler(QBAL("redirect2"), this);
+ profile->installUrlSchemeHandler(QBAL("cors"), this);
+ }
+
+ QList<QUrl> &requests() { return m_requests; }
+
+private:
+ void requestStarted(QWebEngineUrlRequestJob *job) override
+ {
+ QUrl url = job->requestUrl();
+ m_requests << url;
+
+ if (url.scheme() == QBAL("redirect1")) {
+ url.setScheme(QBAL("redirect2"));
+ job->redirect(url);
+ return;
+ }
+
+ QString pathPrefix = QDir(QT_TESTCASE_SOURCEDIR).canonicalPath();
+ QString pathSuffix = url.path();
+ QFile *file = new QFile(pathPrefix + pathSuffix, job);
+ if (!file->open(QIODevice::ReadOnly)) {
+ job->fail(QWebEngineUrlRequestJob::RequestFailed);
+ return;
+ }
+ QByteArray mimeType = QBAL("text/html");
+ if (pathSuffix.endsWith(QSL(".js")))
+ mimeType = QBAL("application/javascript");
+ else if (pathSuffix.endsWith(QSL(".css")))
+ mimeType = QBAL("text/css");
+ job->reply(mimeType, file);
+ }
+
+ QList<QUrl> m_requests;
+};
+
+class tst_Origins final : public QObject {
+ Q_OBJECT
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+ void jsUrlCanon();
+ void jsUrlRelative();
+ void jsUrlOrigin();
+ void subdirWithAccess();
+ void subdirWithoutAccess();
+ void fileAccessRemoteUrl_data();
+ void fileAccessRemoteUrl();
+ void mixedSchemes();
+ void mixedSchemesWithCsp();
+ void mixedXHR_data();
+ void mixedXHR();
+#if defined(WEBSOCKETS)
+ void webSocket();
+#endif
+ void dedicatedWorker();
+ void sharedWorker();
+ void serviceWorker();
+ void viewSource();
+ void createObjectURL();
+ void redirect();
+
+private:
+ bool verifyLoad(const QUrl &url)
+ {
+ QSignalSpy spy(m_page, &QWebEnginePage::loadFinished);
+ m_page->load(url);
+ [&spy]() { QTRY_VERIFY_WITH_TIMEOUT(!spy.isEmpty(), 90000); }();
+ return !spy.isEmpty() && spy.front().value(0).toBool();
+ }
+
+ QVariant eval(const QString &code)
+ {
+ return evaluateJavaScriptSync(m_page, code);
+ }
+
+ QWebEngineProfile m_profile;
+ QWebEnginePage *m_page = nullptr;
+ TstUrlSchemeHandler *m_handler = nullptr;
+};
+
+void tst_Origins::initTestCase()
+{
+ QTest::ignoreMessage(
+ QtWarningMsg,
+ QRegularExpression("Please register the custom scheme 'tst'.*"));
+
+ m_handler = new TstUrlSchemeHandler(&m_profile);
+}
+
+void tst_Origins::cleanupTestCase()
+{
+ QVERIFY(!m_page);
+ delete m_handler;
+}
+
+void tst_Origins::init()
+{
+ m_page = new QWebEnginePage(&m_profile, nullptr);
+}
+
+void tst_Origins::cleanup()
+{
+ delete m_page;
+ m_page = nullptr;
+ m_handler->requests().clear();
+}
+
+// Test URL parsing and canonicalization in Blink. The implementation of this
+// part is mostly shared between Blink and Chromium proper.
+void tst_Origins::jsUrlCanon()
+{
+ QVERIFY(verifyLoad(QSL("about:blank")));
+
+ // Standard schemes are biased towards the authority part.
+ QCOMPARE(eval(QSL("new URL(\"http:foo/bar\").href")), QVariant(QSL("http://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"http:/foo/bar\").href")), QVariant(QSL("http://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"http://foo/bar\").href")), QVariant(QSL("http://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"http:///foo/bar\").href")), QVariant(QSL("http://foo/bar")));
+
+ // The file scheme is however a (particularly) special case.
+#ifdef Q_OS_WIN
+ QCOMPARE(eval(QSL("new URL(\"file:foo/bar\").href")), QVariant(QSL("file://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"file:/foo/bar\").href")), QVariant(QSL("file://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"file://foo/bar\").href")), QVariant(QSL("file://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"file:///foo/bar\").href")), QVariant(QSL("file:///foo/bar")));
+#else
+ QCOMPARE(eval(QSL("new URL(\"file:foo/bar\").href")), QVariant(QSL("file:///foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"file:/foo/bar\").href")), QVariant(QSL("file:///foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"file://foo/bar\").href")), QVariant(QSL("file://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"file:///foo/bar\").href")), QVariant(QSL("file:///foo/bar")));
+#endif
+
+ // The qrc scheme is a PathSyntax scheme, having only a path and nothing else.
+ QCOMPARE(eval(QSL("new URL(\"qrc:foo/bar\").href")), QVariant(QSL("qrc:foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"qrc:/foo/bar\").href")), QVariant(QSL("qrc:/foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"qrc://foo/bar\").href")), QVariant(QSL("qrc://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"qrc:///foo/bar\").href")), QVariant(QSL("qrc:///foo/bar")));
+
+ // Same for unregistered schemes.
+ QCOMPARE(eval(QSL("new URL(\"tst:foo/bar\").href")), QVariant(QSL("tst:foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"tst:/foo/bar\").href")), QVariant(QSL("tst:/foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"tst://foo/bar\").href")), QVariant(QSL("tst://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"tst:///foo/bar\").href")), QVariant(QSL("tst:///foo/bar")));
+
+ // A HostSyntax scheme is like http without the port & user information.
+ QCOMPARE(eval(QSL("new URL(\"HostSyntax:foo/bar\").href")), QVariant(QSL("hostsyntax://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"HostSyntax:foo:42/bar\").href")), QVariant(QSL("hostsyntax://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"HostSyntax:a:b@foo/bar\").href")), QVariant(QSL("hostsyntax://foo/bar")));
+
+ // A HostAndPortSyntax scheme is like http without the user information.
+ QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo/bar\").href")),
+ QVariant(QSL("hostandportsyntax://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo:41/bar\").href")),
+ QVariant(QSL("hostandportsyntax://foo:41/bar")));
+ QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo:42/bar\").href")),
+ QVariant(QSL("hostandportsyntax://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:a:b@foo/bar\").href")),
+ QVariant(QSL("hostandportsyntax://foo/bar")));
+
+ // A HostPortAndUserInformationSyntax scheme is exactly like http.
+ QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo/bar\").href")),
+ QVariant(QSL("hostportanduserinformationsyntax://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo:41/bar\").href")),
+ QVariant(QSL("hostportanduserinformationsyntax://foo:41/bar")));
+ QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo:42/bar\").href")),
+ QVariant(QSL("hostportanduserinformationsyntax://foo/bar")));
+ QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:a:b@foo/bar\").href")),
+ QVariant(QSL("hostportanduserinformationsyntax://a:b@foo/bar")));
+}
+
+// Test relative URL resolution.
+void tst_Origins::jsUrlRelative()
+{
+ QVERIFY(verifyLoad(QSL("about:blank")));
+
+ // Schemes with hosts, like http, work as expected.
+ QCOMPARE(eval(QSL("new URL('bar', 'http://foo').href")), QVariant(QSL("http://foo/bar")));
+ QCOMPARE(eval(QSL("new URL('baz', 'http://foo/bar').href")), QVariant(QSL("http://foo/baz")));
+ QCOMPARE(eval(QSL("new URL('baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/bar/baz")));
+ QCOMPARE(eval(QSL("new URL('/baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz")));
+ QCOMPARE(eval(QSL("new URL('./baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/bar/baz")));
+ QCOMPARE(eval(QSL("new URL('../baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz")));
+ QCOMPARE(eval(QSL("new URL('../../baz', 'http://foo/bar/').href")), QVariant(QSL("http://foo/baz")));
+ QCOMPARE(eval(QSL("new URL('//baz', 'http://foo/bar/').href")), QVariant(QSL("http://baz/")));
+
+ // In the case of schemes without hosts, relative URLs only work if the URL
+ // starts with a single slash -- and canonicalization does not guarantee
+ // this. The following cases all fail with TypeErrors.
+ QCOMPARE(eval(QSL("new URL('bar', 'tst:foo').href")), QVariant());
+ QCOMPARE(eval(QSL("new URL('baz', 'tst:foo/bar').href")), QVariant());
+ QCOMPARE(eval(QSL("new URL('bar', 'tst://foo').href")), QVariant());
+ QCOMPARE(eval(QSL("new URL('bar', 'tst:///foo').href")), QVariant());
+
+ // However, registered custom schemes have been patched to allow relative
+ // URLs even without an initial slash.
+ QCOMPARE(eval(QSL("new URL('bar', 'qrc:foo').href")), QVariant(QSL("qrc:bar")));
+ QCOMPARE(eval(QSL("new URL('baz', 'qrc:foo/bar').href")), QVariant(QSL("qrc:foo/baz")));
+ QCOMPARE(eval(QSL("new URL('bar', 'qrc://foo').href")), QVariant());
+ QCOMPARE(eval(QSL("new URL('bar', 'qrc:///foo').href")), QVariant());
+
+ // With a slash it works the same as http except 'foo' is part of the path and not the host.
+ QCOMPARE(eval(QSL("new URL('bar', 'qrc:/foo').href")), QVariant(QSL("qrc:/bar")));
+ QCOMPARE(eval(QSL("new URL('bar', 'qrc:/foo/').href")), QVariant(QSL("qrc:/foo/bar")));
+ QCOMPARE(eval(QSL("new URL('baz', 'qrc:/foo/bar').href")), QVariant(QSL("qrc:/foo/baz")));
+ QCOMPARE(eval(QSL("new URL('baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/bar/baz")));
+ QCOMPARE(eval(QSL("new URL('/baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz")));
+ QCOMPARE(eval(QSL("new URL('./baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/bar/baz")));
+ QCOMPARE(eval(QSL("new URL('../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/foo/baz")));
+ QCOMPARE(eval(QSL("new URL('../../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz")));
+ QCOMPARE(eval(QSL("new URL('../../../baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc:/baz")));
+
+ // If the relative URL begins with >= 2 slashes, then the scheme is treated
+ // not as a Syntax::Path scheme but as a Syntax::HostPortAndUserInformation
+ // scheme.
+ QCOMPARE(eval(QSL("new URL('//baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc://baz/")));
+ QCOMPARE(eval(QSL("new URL('///baz', 'qrc:/foo/bar/').href")), QVariant(QSL("qrc://baz/")));
+}
+
+// Test origin serialization in Blink, implemented by blink::KURL and
+// blink::SecurityOrigin as opposed to GURL and url::Origin.
+void tst_Origins::jsUrlOrigin()
+{
+ QVERIFY(verifyLoad(QSL("about:blank")));
+
+ // For network protocols the origin string must include the domain and port.
+ QCOMPARE(eval(QSL("new URL(\"http://foo.com/page.html\").origin")), QVariant(QSL("http://foo.com")));
+ QCOMPARE(eval(QSL("new URL(\"https://foo.com/page.html\").origin")), QVariant(QSL("https://foo.com")));
+
+ // Even though file URL can also have domains, these are not included in the
+ // origin string by Chromium. The standard does not specify a value here,
+ // but suggests 'null' (https://url.spec.whatwg.org/#origin).
+ QCOMPARE(eval(QSL("new URL(\"file:/etc/passwd\").origin")), QVariant(QSL("file://")));
+ QCOMPARE(eval(QSL("new URL(\"file://foo.com/etc/passwd\").origin")), QVariant(QSL("file://")));
+
+ // Unregistered schemes behave like file.
+ QCOMPARE(eval(QSL("new URL(\"tst:/banana\").origin")), QVariant(QSL("tst://")));
+ QCOMPARE(eval(QSL("new URL(\"tst://foo.com/banana\").origin")), QVariant(QSL("tst://")));
+
+ // The non-PathSyntax schemes should have hosts and potentially ports.
+ QCOMPARE(eval(QSL("new URL(\"HostSyntax:foo:41/bar\").origin")),
+ QVariant(QSL("hostsyntax://foo")));
+ QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo:41/bar\").origin")),
+ QVariant(QSL("hostandportsyntax://foo:41")));
+ QCOMPARE(eval(QSL("new URL(\"HostAndPortSyntax:foo:42/bar\").origin")),
+ QVariant(QSL("hostandportsyntax://foo")));
+ QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo:41/bar\").origin")),
+ QVariant(QSL("hostportanduserinformationsyntax://foo:41")));
+ QCOMPARE(eval(QSL("new URL(\"HostPortAndUserInformationSyntax:foo:42/bar\").origin")),
+ QVariant(QSL("hostportanduserinformationsyntax://foo")));
+
+ // A PathSyntax scheme should have a 'universal' origin.
+ QCOMPARE(eval(QSL("new URL(\"PathSyntax:foo\").origin")), QVariant(QSL("pathsyntax:")));
+ QCOMPARE(eval(QSL("new URL(\"qrc:/crysis.css\").origin")), QVariant(QSL("qrc:")));
+ QCOMPARE(eval(QSL("new URL(\"qrc://foo.com/crysis.css\").origin")), QVariant(QSL("qrc:")));
+
+ // The NoAccessAllowed flag forces opaque origins.
+ QCOMPARE(eval(QSL("new URL(\"PathSyntax-NoAccessAllowed:foo\").origin")),
+ QVariant(QSL("null")));
+}
+
+class ScopedAttribute {
+public:
+ ScopedAttribute(QWebEngineSettings *settings, QWebEngineSettings::WebAttribute attribute, bool newValue)
+ : m_settings(settings)
+ , m_attribute(attribute)
+ , m_oldValue(m_settings->testAttribute(m_attribute))
+ {
+ m_settings->setAttribute(m_attribute, newValue);
+ }
+ ~ScopedAttribute()
+ {
+ m_settings->setAttribute(m_attribute, m_oldValue);
+ }
+private:
+ QWebEngineSettings *m_settings;
+ QWebEngineSettings::WebAttribute m_attribute;
+ bool m_oldValue;
+};
+
+// Test same-origin policy of file, qrc and custom schemes.
+//
+// Note the test case involves the main page trying to load an iframe from a
+// file that resides in a parent directory. This is just a small detail to
+// demonstrate the difference with Firefox where such access is not allowed.
+void tst_Origins::subdirWithAccess()
+{
+ ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, true);
+
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/subdir/index.html"));
+ QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
+ QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
+
+ QVERIFY(verifyLoad(QSL("qrc:/resources/subdir/index.html")));
+ QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
+ QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
+
+ QVERIFY(verifyLoad(QSL("tst:/resources/subdir/index.html")));
+ QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
+ QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
+}
+
+// In this variation the LocalContentCanAccessFileUrls attribute is disabled. As
+// a result all file URLs will be considered to have unique/opaque origins, that
+// is, they are not the 'same origin as' any other origin.
+//
+// Note that this applies only to file URLs and not qrc or custom schemes.
+//
+// See also (in Blink):
+// - the allow_file_access_from_file_urls option and
+// - the blink::SecurityOrigin::BlockLocalAccessFromLocalOrigin() method.
+void tst_Origins::subdirWithoutAccess()
+{
+ ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, false);
+
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/subdir/index.html"));
+ QCOMPARE(eval(QSL("msg[0]")), QVariant());
+ QCOMPARE(eval(QSL("msg[1]")), QVariant());
+
+ QVERIFY(verifyLoad(QSL("qrc:/resources/subdir/index.html")));
+ QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
+ QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
+
+ QVERIFY(verifyLoad(QSL("tst:/resources/subdir/index.html")));
+ QCOMPARE(eval(QSL("msg[0]")), QVariant(QSL("hello")));
+ QCOMPARE(eval(QSL("msg[1]")), QVariant(QSL("world")));
+}
+
+void tst_Origins::fileAccessRemoteUrl_data()
+{
+ QTest::addColumn<bool>("EnableAccess");
+ QTest::addRow("enabled") << true;
+ QTest::addRow("disabled") << false;
+}
+
+void tst_Origins::fileAccessRemoteUrl()
+{
+ QFETCH(bool, EnableAccess);
+
+ HttpServer server;
+ server.setResourceDirs({ QDir(QT_TESTCASE_SOURCEDIR).canonicalPath() + "/resources" });
+ QVERIFY(server.start());
+
+ ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessRemoteUrls, EnableAccess);
+ if (!EnableAccess)
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("blocked by CORS policy")));
+
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.html"));
+
+ eval("sendXHR('" + server.url("/mixedXHR.txt").toString() + "')");
+ QTRY_COMPARE(eval("result"), (EnableAccess ? QString("ok") : QString("error")));
+}
+
+// Load the main page over one scheme with an iframe over another scheme.
+//
+// For file and qrc schemes, the iframe should load but it should not be
+// possible for scripts in different frames to interact.
+//
+// Additionally for unregistered custom schemes and custom schemes without
+// LocalAccessAllowed it should not be possible to load an iframe over the
+// file: scheme.
+void tst_Origins::mixedSchemes()
+{
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedSchemes.html"));
+ eval("setIFrameUrl('file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedSchemes_frame.html')");
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('qrc:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('tst:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+
+ QVERIFY(verifyLoad(QSL("qrc:/resources/mixedSchemes.html")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval("setIFrameUrl('file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedSchemes_frame.html')");
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ eval(QSL("setIFrameUrl('qrc:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('tst:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+
+ QVERIFY(verifyLoad(QSL("tst:/resources/mixedSchemes.html")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Not allowed to load local resource")));
+ eval("setIFrameUrl('file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedSchemes_frame.html')");
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("cannotLoad")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('qrc:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ eval(QSL("setIFrameUrl('tst:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
+
+ QVERIFY(verifyLoad(QSL("PathSyntax:/resources/mixedSchemes.html")));
+ eval(QSL("setIFrameUrl('PathSyntax:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Not allowed to load local resource")));
+ eval(QSL("setIFrameUrl('PathSyntax-Local:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("cannotLoad")));
+ eval(QSL("setIFrameUrl('PathSyntax-LocalAccessAllowed:/resources/mixedSchemes_frame.html')"));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('PathSyntax-NoAccessAllowed:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+
+ QVERIFY(verifyLoad(QSL("PathSyntax-LocalAccessAllowed:/resources/mixedSchemes.html")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('PathSyntax:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('PathSyntax-Local:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ eval(QSL("setIFrameUrl('PathSyntax-LocalAccessAllowed:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('PathSyntax-NoAccessAllowed:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+
+ QVERIFY(verifyLoad(QSL("PathSyntax-NoAccessAllowed:/resources/mixedSchemes.html")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('PathSyntax:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Not allowed to load local resource")));
+ eval(QSL("setIFrameUrl('PathSyntax-Local:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("cannotLoad")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('PathSyntax-LocalAccessAllowed:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('PathSyntax-NoAccessAllowed:/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+
+ QVERIFY(verifyLoad(QSL("HostSyntax://a/resources/mixedSchemes.html")));
+ eval(QSL("setIFrameUrl('HostSyntax://a/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('HostSyntax://b/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+}
+
+// Like mixedSchemes but adds a Content-Security-Policy: frame-src 'none' header.
+void tst_Origins::mixedSchemesWithCsp()
+{
+ QVERIFY(verifyLoad(QSL("HostSyntax://a/resources/mixedSchemesWithCsp.html")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("violates the following Content Security Policy")));
+ eval(QSL("setIFrameUrl('HostSyntax://a/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("violates the following Content Security Policy")));
+ eval(QSL("setIFrameUrl('HostSyntax://b/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+
+ QVERIFY(verifyLoad(QSL("HostSyntax-ContentSecurityPolicyIgnored://a/resources/mixedSchemesWithCsp.html")));
+ eval(QSL("setIFrameUrl('HostSyntax-ContentSecurityPolicyIgnored://a/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadAndAccess")));
+ QTest::ignoreMessage(QtSystemMsg, QRegularExpression(QSL("Uncaught SecurityError")));
+ eval(QSL("setIFrameUrl('HostSyntax-ContentSecurityPolicyIgnored://b/resources/mixedSchemes_frame.html')"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("canLoadButNotAccess")));
+}
+
+// Load the main page over one scheme, then make an XMLHttpRequest to a
+// different scheme.
+//
+// Cross-origin XMLHttpRequests can only be made to CORS-enabled schemes. These
+// include the builtin schemes http, https, data, and chrome, as well as custom
+// schemes with the CorsEnabled flag.
+void tst_Origins::mixedXHR_data()
+{
+ QTest::addColumn<QString>("url");
+ QTest::addColumn<QString>("command");
+ QTest::addColumn<QVariant>("result");
+ QTest::newRow("file->file") << QString("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.html")
+ << QString("sendXHR('file:"
+ + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.txt')")
+ << QVariant(QString("ok"));
+ QTest::newRow("file->qrc") << QString("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.html")
+ << QString("sendXHR('qrc:/resources/mixedXHR.txt')")
+ << QVariant(QString("error"));
+ QTest::newRow("file->tst") << QString("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.html")
+ << QString("sendXHR('tst:/resources/mixedXHR.txt')")
+ << QVariant(QString("error"));
+ QTest::newRow("file->data") << QString("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.html")
+ << QString("sendXHR('data:,ok')") << QVariant(QString("ok"));
+ QTest::newRow("file->cors") << QString("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.html")
+ << QString("sendXHR('cors:/resources/mixedXHR.txt')")
+ << QVariant(QString("ok"));
+
+ QTest::newRow("qrc->file") << QString("qrc:/resources/mixedXHR.html")
+ << QString("sendXHR('file:"
+ + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.txt')")
+ << QVariant(QString("ok"));
+ QTest::newRow("qrc->qrc") << QString("qrc:/resources/mixedXHR.html")
+ << QString("sendXHR('qrc:/resources/mixedXHR.txt')")
+ << QVariant(QString("ok"));
+ QTest::newRow("qrc->tst") << QString("qrc:/resources/mixedXHR.html")
+ << QString("sendXHR('tst:/resources/mixedXHR.txt')")
+ << QVariant(QString("error"));
+ QTest::newRow("qrc->data") << QString("qrc:/resources/mixedXHR.html")
+ << QString("sendXHR('data:,ok')")
+ << QVariant(QString("ok"));
+ QTest::newRow("qrc->cors") << QString("qrc:/resources/mixedXHR.html")
+ << QString("sendXHR('cors:/resources/mixedXHR.txt')")
+ << QVariant(QString("ok"));
+
+ QTest::newRow("tst->file") << QString("tst:/resources/mixedXHR.html")
+ << QString("sendXHR('file:"
+ + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/mixedXHR.txt')")
+ << QVariant(QString("error"));
+ QTest::newRow("tst->qrc") << QString("tst:/resources/mixedXHR.html")
+ << QString("sendXHR('qrc:/resources/mixedXHR.txt')")
+ << QVariant(QString("error"));
+ QTest::newRow("tst->tst") << QString("tst:/resources/mixedXHR.html")
+ << QString("sendXHR('tst:/resources/mixedXHR.txt')")
+ << QVariant(QString("ok"));
+ QTest::newRow("tst->data") << QString("tst:/resources/mixedXHR.html")
+ << QString("sendXHR('data:,ok')")
+ << QVariant(QString("ok"));
+ QTest::newRow("tst->cors") << QString("tst:/resources/mixedXHR.html")
+ << QString("sendXHR('cors:/resources/mixedXHR.txt')")
+ << QVariant(QString("ok"));
+
+}
+
+
+void tst_Origins::mixedXHR()
+{
+ QFETCH(QString, url);
+ QFETCH(QString, command);
+ QFETCH(QVariant, result);
+
+ QVERIFY(verifyLoad(url));
+ eval(command);
+ QTRY_COMPARE(eval(QString("result")), result);
+}
+
+#if defined(WEBSOCKETS)
+class EchoServer : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(QUrl url READ url NOTIFY urlChanged)
+public:
+ EchoServer() : webSocketServer(QSL("EchoServer"), QWebSocketServer::NonSecureMode)
+ {
+ connect(&webSocketServer, &QWebSocketServer::newConnection, this, &EchoServer::onNewConnection);
+ }
+
+ bool listen()
+ {
+ if (webSocketServer.listen(QHostAddress::Any)) {
+ Q_EMIT urlChanged();
+ return true;
+ }
+ return false;
+ }
+
+ QUrl url() const
+ {
+ return webSocketServer.serverUrl();
+ }
+
+Q_SIGNALS:
+ void urlChanged();
+
+private:
+ void onNewConnection()
+ {
+ QWebSocket *socket = webSocketServer.nextPendingConnection();
+ connect(socket, &QWebSocket::textMessageReceived, this, &EchoServer::onTextMessageReceived);
+ connect(socket, &QWebSocket::disconnected, socket, &QObject::deleteLater);
+ }
+
+ void onTextMessageReceived(const QString &message)
+ {
+ QWebSocket *socket = qobject_cast<QWebSocket *>(sender());
+ socket->sendTextMessage(message);
+ }
+
+ QWebSocketServer webSocketServer;
+};
+
+// Try opening a WebSocket from pages loaded over various URL schemes.
+void tst_Origins::webSocket()
+{
+ EchoServer echoServer;
+ QWebChannel channel;
+ channel.registerObject(QSL("echoServer"), &echoServer);
+ m_page->setWebChannel(&channel);
+ QVERIFY(echoServer.listen());
+
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/websocket.html"));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
+
+ QVERIFY(verifyLoad(QSL("qrc:/resources/websocket.html")));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
+
+ // Unregistered schemes can also open WebSockets (since Chromium 71)
+ QVERIFY(verifyLoad(QSL("tst:/resources/websocket.html")));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
+
+ // Even an insecure registered scheme can open WebSockets.
+ QVERIFY(verifyLoad(QSL("PathSyntax:/resources/websocket.html")));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
+}
+#endif
+// Create a (Dedicated)Worker. Since dedicated workers can only be accessed from
+// one page, there is not much need for security restrictions.
+void tst_Origins::dedicatedWorker()
+{
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/dedicatedWorker.html"));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
+ QVERIFY(verifyLoad(QSL("qrc:/resources/dedicatedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
+ // Unregistered schemes can also create Workers (since Chromium 71)
+ QVERIFY(verifyLoad(QSL("tst:/resources/dedicatedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
+ // Even an insecure registered scheme can create Workers.
+ QVERIFY(verifyLoad(QSL("PathSyntax:/resources/dedicatedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
+ // But not if the NoAccessAllowed flag is set.
+ QVERIFY(verifyLoad(QSL("PathSyntax-NoAccessAllowed:/resources/dedicatedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("cannot be accessed from origin 'null'")));
+}
+
+// Create a SharedWorker. Shared workers can be accessed from multiple pages,
+// and therefore the same-origin policy applies.
+void tst_Origins::sharedWorker()
+{
+ {
+ ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, false);
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/sharedWorker.html"));
+ QTRY_VERIFY_WITH_TIMEOUT(eval(QSL("done")).toBool(), 10000);
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("cannot be accessed from origin 'null'")));
+ }
+
+ {
+ ScopedAttribute sa(m_page->settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, true);
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/sharedWorker.html"));
+ QTRY_VERIFY_WITH_TIMEOUT(eval(QSL("done")).toBool(), 10000);
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+ }
+
+ QVERIFY(verifyLoad(QSL("qrc:/resources/sharedWorker.html")));
+ QTRY_VERIFY_WITH_TIMEOUT(eval(QSL("done")).toBool(), 10000);
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
+ // Unregistered schemes should not create SharedWorkers.
+
+ QVERIFY(verifyLoad(QSL("PathSyntax:/resources/sharedWorker.html")));
+ QTRY_VERIFY_WITH_TIMEOUT(eval(QSL("done")).toBool(), 10000);
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
+ QVERIFY(verifyLoad(QSL("PathSyntax-NoAccessAllowed:/resources/sharedWorker.html")));
+ QTRY_VERIFY_WITH_TIMEOUT(eval(QSL("done")).toBool(), 10000);
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("denied to origin 'null'")));
+}
+
+// Service workers have to be explicitly enabled for a scheme.
+void tst_Origins::serviceWorker()
+{
+ QVERIFY(verifyLoad("file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/serviceWorker.html"));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("The URL protocol of the current origin ('file://') is not supported.")));
+
+ QVERIFY(verifyLoad(QSL("qrc:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("The URL protocol of the current origin ('qrc:') is not supported.")));
+
+ QVERIFY(verifyLoad(QSL("tst:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("Cannot read property 'register' of undefined")));
+
+ QVERIFY(verifyLoad(QSL("PathSyntax:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("Cannot read property 'register' of undefined")));
+
+ QVERIFY(verifyLoad(QSL("PathSyntax-Secure:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("The URL protocol of the current origin ('pathsyntax-secure:') is not supported.")));
+
+ QVERIFY(verifyLoad(QSL("PathSyntax-ServiceWorkersAllowed:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("Cannot read property 'register' of undefined")));
+
+ QVERIFY(verifyLoad(QSL("PathSyntax-Secure-ServiceWorkersAllowed:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("error")), QVariant());
+
+ QVERIFY(verifyLoad(QSL("PathSyntax-NoAccessAllowed:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("Cannot read property 'register' of undefined")));
+}
+
+// Support for view-source must be enabled explicitly.
+void tst_Origins::viewSource()
+{
+ QVERIFY(verifyLoad("view-source:file:" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/viewSource.html"));
+#ifdef Q_OS_WIN
+ QCOMPARE(m_page->requestedUrl().toString(),
+ "file:///" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/viewSource.html");
+#else
+ QCOMPARE(m_page->requestedUrl().toString(),
+ "file://" + QDir(QT_TESTCASE_SOURCEDIR).canonicalPath()
+ + "/resources/viewSource.html");
+#endif
+
+ QVERIFY(verifyLoad(QSL("view-source:qrc:/resources/viewSource.html")));
+ QCOMPARE(m_page->requestedUrl().toString(), QSL("qrc:/resources/viewSource.html"));
+
+ QVERIFY(verifyLoad(QSL("view-source:tst:/resources/viewSource.html")));
+ QCOMPARE(m_page->requestedUrl().toString(), QSL("about:blank"));
+
+ QVERIFY(verifyLoad(QSL("view-source:PathSyntax:/resources/viewSource.html")));
+ QCOMPARE(m_page->requestedUrl().toString(), QSL("about:blank"));
+
+ QVERIFY(verifyLoad(QSL("view-source:PathSyntax-ViewSourceAllowed:/resources/viewSource.html")));
+ QCOMPARE(m_page->requestedUrl().toString(), QSL("pathsyntax-viewsourceallowed:/resources/viewSource.html"));
+}
+
+void tst_Origins::createObjectURL()
+{
+ // Legal for registered custom schemes.
+ QVERIFY(verifyLoad(QSL("qrc:/resources/createObjectURL.html")));
+ QVERIFY(eval(QSL("result")).toString().startsWith(QSL("blob:qrc:")));
+
+ // Also legal for unregistered schemes (since Chromium 71)
+ QVERIFY(verifyLoad(QSL("tst:/resources/createObjectURL.html")));
+ QVERIFY(eval(QSL("result")).toString().startsWith(QSL("blob:tst:")));
+}
+
+void tst_Origins::redirect()
+{
+ QVERIFY(verifyLoad(QSL("redirect1:/resources/redirect.html")));
+ QTRY_COMPARE(m_handler->requests().size(), 7);
+ QCOMPARE(m_handler->requests()[0], QUrl(QStringLiteral("redirect1:/resources/redirect.html")));
+ QCOMPARE(m_handler->requests()[1], QUrl(QStringLiteral("redirect2:/resources/redirect.html")));
+ QCOMPARE(m_handler->requests()[2], QUrl(QStringLiteral("redirect1:/resources/redirect.css")));
+ QCOMPARE(m_handler->requests()[3], QUrl(QStringLiteral("redirect2:/resources/redirect.css")));
+ QCOMPARE(m_handler->requests()[4], QUrl(QStringLiteral("redirect1:/resources/Akronim-Regular.woff2")));
+ QCOMPARE(m_handler->requests()[5], QUrl(QStringLiteral("redirect1:/resources/Akronim-Regular.woff2")));
+ QCOMPARE(m_handler->requests()[6], QUrl(QStringLiteral("redirect2:/resources/Akronim-Regular.woff2")));
+}
+
+QTEST_MAIN(tst_Origins)
+#include "tst_origins.moc"
diff --git a/tests/auto/core/origins/tst_origins.qrc b/tests/auto/core/origins/tst_origins.qrc
new file mode 100644
index 000000000..fcf54aaea
--- /dev/null
+++ b/tests/auto/core/origins/tst_origins.qrc
@@ -0,0 +1,22 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+<qresource>
+ <file>resources/createObjectURL.html</file>
+ <file>resources/dedicatedWorker.html</file>
+ <file>resources/dedicatedWorker.js</file>
+ <file>resources/mixedSchemes.html</file>
+ <file>resources/mixedSchemesWithCsp.html</file>
+ <file>resources/mixedSchemes_frame.html</file>
+ <file>resources/mixedXHR.html</file>
+ <file>resources/mixedXHR.txt</file>
+ <file>resources/serviceWorker.html</file>
+ <file>resources/serviceWorker.js</file>
+ <file>resources/sharedWorker.html</file>
+ <file>resources/sharedWorker.js</file>
+ <file>resources/subdir/frame2.html</file>
+ <file>resources/subdir/index.html</file>
+ <file>resources/subdir_frame1.html</file>
+ <file>resources/viewSource.html</file>
+ <file>resources/websocket.html</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/core/qwebenginecookiestore/CMakeLists.txt b/tests/auto/core/qwebenginecookiestore/CMakeLists.txt
index 6125b4f12..33ba5ff1a 100644
--- a/tests/auto/core/qwebenginecookiestore/CMakeLists.txt
+++ b/tests/auto/core/qwebenginecookiestore/CMakeLists.txt
@@ -5,7 +5,7 @@ qt_internal_add_test(tst_qwebenginecookiestore
SOURCES
tst_qwebenginecookiestore.cpp
LIBRARIES
- Qt::WebEngineWidgets
+ Qt::WebEngineCore
Test::HttpServer
Test::Util
)
diff --git a/tests/auto/core/qwebenginesettings/BLACKLIST b/tests/auto/core/qwebenginesettings/BLACKLIST
new file mode 100644
index 000000000..d4a35a76a
--- /dev/null
+++ b/tests/auto/core/qwebenginesettings/BLACKLIST
@@ -0,0 +1,2 @@
+[javascriptClipboard]
+ubuntu-20.04
diff --git a/tests/auto/core/qwebenginesettings/CMakeLists.txt b/tests/auto/core/qwebenginesettings/CMakeLists.txt
new file mode 100644
index 000000000..7f8b49d1b
--- /dev/null
+++ b/tests/auto/core/qwebenginesettings/CMakeLists.txt
@@ -0,0 +1,9 @@
+include(../../util/util.cmake)
+
+qt_internal_add_test(tst_qwebenginesettings
+ SOURCES
+ tst_qwebenginesettings.cpp
+ LIBRARIES
+ Qt::WebEngineCore
+ Test::Util
+)
diff --git a/tests/auto/core/qwebenginesettings/qwebenginesettings.pro b/tests/auto/core/qwebenginesettings/qwebenginesettings.pro
new file mode 100644
index 000000000..70786e70f
--- /dev/null
+++ b/tests/auto/core/qwebenginesettings/qwebenginesettings.pro
@@ -0,0 +1,2 @@
+include(../tests.pri)
+QT *= core-private gui-private
diff --git a/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp b/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp
new file mode 100644
index 000000000..4220f496b
--- /dev/null
+++ b/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp
@@ -0,0 +1,198 @@
+/*
+ Copyright (C) 2015 The Qt Company Ltd.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <util.h>
+
+#include <QtTest/QtTest>
+
+#include <qwebenginepage.h>
+#include <qwebengineprofile.h>
+#include <qwebenginesettings.h>
+
+#include <QtGui/qclipboard.h>
+#include <QtGui/qguiapplication.h>
+
+class tst_QWebEngineSettings: public QObject {
+ Q_OBJECT
+
+private Q_SLOTS:
+ void resetAttributes();
+ void defaultFontFamily_data();
+ void defaultFontFamily();
+ void javascriptClipboard_data();
+ void javascriptClipboard();
+ void setInAcceptNavigationRequest();
+};
+
+void tst_QWebEngineSettings::resetAttributes()
+{
+ QWebEngineProfile profile;
+ QWebEngineSettings *settings = profile.settings();
+
+ // Attribute
+ bool defaultValue = settings->testAttribute(QWebEngineSettings::FullScreenSupportEnabled);
+ settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, !defaultValue);
+ QCOMPARE(!defaultValue, settings->testAttribute(QWebEngineSettings::FullScreenSupportEnabled));
+ settings->resetAttribute(QWebEngineSettings::FullScreenSupportEnabled);
+ QCOMPARE(defaultValue, settings->testAttribute(QWebEngineSettings::FullScreenSupportEnabled));
+
+ // Font family
+ QString defaultFamily = settings->fontFamily(QWebEngineSettings::StandardFont);
+ QString newFontFamily("PugDog");
+ settings->setFontFamily(QWebEngineSettings::StandardFont, newFontFamily);
+ QCOMPARE(newFontFamily, settings->fontFamily(QWebEngineSettings::StandardFont));
+ settings->resetFontFamily(QWebEngineSettings::StandardFont);
+ QCOMPARE(defaultFamily, settings->fontFamily(QWebEngineSettings::StandardFont));
+
+ // Font size
+ int defaultSize = settings->fontSize(QWebEngineSettings::MinimumFontSize);
+ int newSize = defaultSize + 10;
+ settings->setFontSize(QWebEngineSettings::MinimumFontSize, newSize);
+ QCOMPARE(newSize, settings->fontSize(QWebEngineSettings::MinimumFontSize));
+ settings->resetFontSize(QWebEngineSettings::MinimumFontSize);
+ QCOMPARE(defaultSize, settings->fontSize(QWebEngineSettings::MinimumFontSize));
+}
+
+void tst_QWebEngineSettings::defaultFontFamily_data()
+{
+ QTest::addColumn<int>("fontFamily");
+
+ QTest::newRow("StandardFont") << static_cast<int>(QWebEngineSettings::StandardFont);
+ QTest::newRow("FixedFont") << static_cast<int>(QWebEngineSettings::FixedFont);
+ QTest::newRow("SerifFont") << static_cast<int>(QWebEngineSettings::SerifFont);
+ QTest::newRow("SansSerifFont") << static_cast<int>(QWebEngineSettings::SansSerifFont);
+ QTest::newRow("CursiveFont") << static_cast<int>(QWebEngineSettings::CursiveFont);
+ QTest::newRow("FantasyFont") << static_cast<int>(QWebEngineSettings::FantasyFont);
+}
+
+void tst_QWebEngineSettings::defaultFontFamily()
+{
+ QWebEngineProfile profile;
+ QWebEngineSettings *settings = profile.settings();
+
+ QFETCH(int, fontFamily);
+ QVERIFY(!settings->fontFamily(static_cast<QWebEngineSettings::FontFamily>(fontFamily)).isEmpty());
+}
+
+void tst_QWebEngineSettings::javascriptClipboard_data()
+{
+ QTest::addColumn<bool>("javascriptCanAccessClipboard");
+ QTest::addColumn<bool>("javascriptCanPaste");
+ QTest::addColumn<bool>("copyResult");
+ QTest::addColumn<bool>("pasteResult");
+
+ QTest::newRow("default") << false << false << false << false;
+ QTest::newRow("canCopy") << true << false << true << false;
+ // paste command requires both permissions
+ QTest::newRow("canPaste") << false << true << false << false;
+ QTest::newRow("canCopyAndPaste") << true << true << true << true;
+}
+
+void tst_QWebEngineSettings::javascriptClipboard()
+{
+ QFETCH(bool, javascriptCanAccessClipboard);
+ QFETCH(bool, javascriptCanPaste);
+ QFETCH(bool, copyResult);
+ QFETCH(bool, pasteResult);
+
+ QWebEnginePage page;
+
+ // check defaults
+ QCOMPARE(page.settings()->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard),
+ false);
+ QCOMPARE(page.settings()->testAttribute(QWebEngineSettings::JavascriptCanPaste), false);
+
+ // check accessors
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard,
+ javascriptCanAccessClipboard);
+ page.settings()->setAttribute(QWebEngineSettings::JavascriptCanPaste,
+ javascriptCanPaste);
+ QCOMPARE(page.settings()->testAttribute(QWebEngineSettings::JavascriptCanAccessClipboard),
+ javascriptCanAccessClipboard);
+ QCOMPARE(page.settings()->testAttribute(QWebEngineSettings::JavascriptCanPaste),
+ javascriptCanPaste);
+
+ QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+ page.setHtml("<html><body>"
+ "<input type='text' value='OriginalText' id='myInput'/>"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+
+ // make sure that 'OriginalText' is selected
+ evaluateJavaScriptSync(&page, "document.getElementById('myInput').select()");
+ QCOMPARE(evaluateJavaScriptSync(&page, "window.getSelection().toString()").toString(),
+ QStringLiteral("OriginalText"));
+
+ // Check that the actual settings work by the
+ // - return value of queryCommandEnabled and
+ // - return value of execCommand
+ // - comparing the clipboard / input field
+ QGuiApplication::clipboard()->clear();
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.queryCommandEnabled('copy')").toBool(),
+ copyResult);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.execCommand('copy')").toBool(), copyResult);
+ QTRY_COMPARE(QGuiApplication::clipboard()->text(),
+ (copyResult ? QString("OriginalText") : QString()));
+
+
+ QGuiApplication::clipboard()->setText("AnotherText");
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.queryCommandEnabled('paste')").toBool(),
+ pasteResult);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.execCommand('paste')").toBool(), pasteResult);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.getElementById('myInput').value").toString(),
+ (pasteResult ? QString("AnotherText") : QString("OriginalText")));
+}
+
+class NavigationRequestOverride : public QWebEnginePage
+{
+protected:
+ bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) override
+ {
+ Q_UNUSED(type);
+
+ if (isMainFrame && url.scheme().startsWith("data"))
+ settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
+ // TODO: note this setting is flaky, consider settings().commit()
+ return true;
+ }
+};
+
+void tst_QWebEngineSettings::setInAcceptNavigationRequest()
+{
+ NavigationRequestOverride page;
+ QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+ QWebEngineProfile::defaultProfile()->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
+ QVERIFY(!page.settings()->testAttribute(QWebEngineSettings::JavascriptEnabled));
+
+ page.load(QUrl("about:blank"));
+ QVERIFY(loadFinishedSpy.wait());
+ QVERIFY(!page.settings()->testAttribute(QWebEngineSettings::JavascriptEnabled));
+
+ page.setHtml("<html><body>"
+ "<script>document.write('PASS')</script>"
+ "<noscript>FAIL</noscript>"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+ QVERIFY(page.settings()->testAttribute(QWebEngineSettings::JavascriptEnabled));
+ QCOMPARE(toPlainTextSync(&page), QStringLiteral("PASS"));
+}
+
+QTEST_MAIN(tst_QWebEngineSettings)
+
+#include "tst_qwebenginesettings.moc"
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt b/tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt
index 96a06c1b9..0f8d90a08 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/CMakeLists.txt
@@ -5,7 +5,7 @@ qt_internal_add_test(tst_qwebengineurlrequestinterceptor
SOURCES
tst_qwebengineurlrequestinterceptor.cpp
LIBRARIES
- Qt::WebEngineWidgets
+ Qt::WebEngineCore
Test::HttpServer
Test::Util
)
diff --git a/tests/auto/core/tests.pri b/tests/auto/core/tests.pri
index 59d6c0865..2f34f1735 100644
--- a/tests/auto/core/tests.pri
+++ b/tests/auto/core/tests.pri
@@ -10,7 +10,7 @@ INCLUDEPATH += $$PWD
exists($$_PRO_FILE_PWD_/$${TARGET}.qrc): RESOURCES += $${TARGET}.qrc
-QT += testlib network webenginewidgets widgets
+QT += testlib network webenginecore
# This define is used by some tests to look up resources in the source tree
DEFINES += TESTS_SOURCE_DIR=\\\"$$PWD/\\\"