summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/auto.pro2
-rw-r--r--tests/auto/core/core.pro7
-rw-r--r--tests/auto/core/qwebenginecookiestoreclient/qwebenginecookiestoreclient.pro1
-rw-r--r--tests/auto/core/qwebenginecookiestoreclient/resources/content.html5
-rw-r--r--tests/auto/core/qwebenginecookiestoreclient/resources/index.html38
-rw-r--r--tests/auto/core/qwebenginecookiestoreclient/tst_qwebenginecookiestoreclient.cpp208
-rw-r--r--tests/auto/core/qwebenginecookiestoreclient/tst_qwebenginecookiestoreclient.qrc6
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/qwebengineurlrequestinterceptor.pro1
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/resources/content.html5
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/resources/firstparty.html5
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/resources/index.html16
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp277
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc7
-rw-r--r--tests/auto/core/tests.pri17
-rw-r--r--tests/auto/quick/inspectorserver/tst_inspectorserver.cpp2
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp211
-rw-r--r--tests/auto/quick/qmltests/data/TestWebEngineView.qml9
-rw-r--r--tests/auto/quick/qmltests/data/confirmclose.html5
-rw-r--r--tests/auto/quick/qmltests/data/directoryupload.html16
-rw-r--r--tests/auto/quick/qmltests/data/forms.html40
-rw-r--r--tests/auto/quick/qmltests/data/multifileupload.html17
-rw-r--r--tests/auto/quick/qmltests/data/singlefileupload.html17
-rw-r--r--tests/auto/quick/qmltests/data/titleupdate.js55
-rw-r--r--tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml82
-rw-r--r--tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_favIconLoad.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_filePicker.qml129
-rw-r--r--tests/auto/quick/qmltests/data/tst_findText.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_formValidation.qml124
-rw-r--r--tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml35
-rw-r--r--tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_linkHovered.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_loadFail.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_loadHtml.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_loadProgress.qml23
-rw-r--r--tests/auto/quick/qmltests/data/tst_loadProgressSignal.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_loadUrl.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_navigationHistory.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_navigationRequested.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_properties.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_runJavaScript.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_titleChanged.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_userScripts.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_webchannel.qml2
-rw-r--r--tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/FilePicker.qml60
-rw-r--r--tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/qmldir1
-rw-r--r--tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml49
-rw-r--r--tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir1
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro11
-rw-r--r--tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp34
-rw-r--r--tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp2
-rw-r--r--tests/auto/widgets/qwebengineaccessibility/qwebengineaccessibility.pro1
-rw-r--r--tests/auto/widgets/qwebengineframe/qwebengineframe.pro2
-rw-r--r--tests/auto/widgets/qwebengineframe/tst_qwebengineframe.cpp1654
-rw-r--r--tests/auto/widgets/qwebengineframe/tst_qwebengineframe.qrc10
-rw-r--r--tests/auto/widgets/qwebenginehistory/qwebenginehistory.pro1
-rw-r--r--tests/auto/widgets/qwebenginehistoryinterface/qwebenginehistoryinterface.pro1
-rw-r--r--tests/auto/widgets/qwebengineinspector/qwebengineinspector.pro1
-rw-r--r--tests/auto/widgets/qwebenginepage/qwebenginepage.pro1
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/fullscreen.html10
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/image.png (renamed from tests/auto/widgets/qwebengineframe/resources/image.png)bin14743 -> 14743 bytes
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/style.css (renamed from tests/auto/widgets/qwebengineframe/resources/style.css)0
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/test1.html (renamed from tests/auto/widgets/qwebengineframe/resources/test1.html)0
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/test2.html (renamed from tests/auto/widgets/qwebengineframe/resources/test2.html)0
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/testiframe.html (renamed from tests/auto/widgets/qwebengineframe/resources/testiframe.html)0
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/testiframe2.html (renamed from tests/auto/widgets/qwebengineframe/resources/testiframe2.html)0
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp1785
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc9
-rw-r--r--tests/auto/widgets/qwebenginescript/qwebenginescript.pro1
-rw-r--r--tests/auto/widgets/qwebengineview/qwebengineview.pro1
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp3
-rw-r--r--tests/auto/widgets/tests.pri2
-rw-r--r--tests/auto/widgets/util.h5
-rw-r--r--tests/auto/widgets/widgets.pro1
-rw-r--r--tests/quicktestbrowser/ApplicationRoot.qml2
-rw-r--r--tests/quicktestbrowser/BrowserWindow.qml28
-rw-r--r--tests/quicktestbrowser/FullScreenNotification.qml99
-rw-r--r--tests/quicktestbrowser/main.cpp27
-rw-r--r--tests/quicktestbrowser/quicktestbrowser.pro3
-rw-r--r--tests/quicktestbrowser/resources.qrc1
82 files changed, 3176 insertions, 2026 deletions
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index f14305f72..06430cf8e 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -4,4 +4,6 @@ SUBDIRS = quick
qtHaveModule(webenginewidgets) {
SUBDIRS += widgets
+# core tests depend on widgets for now
+ SUBDIRS += core
}
diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro
new file mode 100644
index 000000000..ed0a61532
--- /dev/null
+++ b/tests/auto/core/core.pro
@@ -0,0 +1,7 @@
+TEMPLATE = subdirs
+
+CONFIG += ordered
+
+SUBDIRS += \
+ qwebenginecookiestoreclient \
+ qwebengineurlrequestinterceptor \
diff --git a/tests/auto/core/qwebenginecookiestoreclient/qwebenginecookiestoreclient.pro b/tests/auto/core/qwebenginecookiestoreclient/qwebenginecookiestoreclient.pro
new file mode 100644
index 000000000..e99c7f493
--- /dev/null
+++ b/tests/auto/core/qwebenginecookiestoreclient/qwebenginecookiestoreclient.pro
@@ -0,0 +1 @@
+include(../tests.pri)
diff --git a/tests/auto/core/qwebenginecookiestoreclient/resources/content.html b/tests/auto/core/qwebenginecookiestoreclient/resources/content.html
new file mode 100644
index 000000000..360ad65ef
--- /dev/null
+++ b/tests/auto/core/qwebenginecookiestoreclient/resources/content.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<a>This is test content</a>
+</body>
+</html>
diff --git a/tests/auto/core/qwebenginecookiestoreclient/resources/index.html b/tests/auto/core/qwebenginecookiestoreclient/resources/index.html
new file mode 100644
index 000000000..d41866712
--- /dev/null
+++ b/tests/auto/core/qwebenginecookiestoreclient/resources/index.html
@@ -0,0 +1,38 @@
+<html>
+ <head>
+ <script type="text/javascript">
+ function generateCookieString(key, value, options) {
+ key = key.replace(/[^#$&+\^`|]/g, encodeURIComponent);
+ key = key.replace(/\(/g, '%28').replace(/\)/g, '%29');
+ value = (value + '').replace(/[^!#$&-+\--:<-\[\]-~]/g, encodeURIComponent);
+ options = options || {};
+
+ var cookieString = key + '=' + value;
+ cookieString += options.path ? '; Path=' + options.path : '';
+ cookieString += options.domain ? '; Domain=' + options.domain : '';
+ cookieString += options.expires ? '; Expires=' + options.expires.toUTCString() : '';
+ cookieString += options.secure ? '; Secure' : '';
+
+ console.log(cookieString)
+ return cookieString;
+};
+function setCookie() {
+ var name = "SessionCookie"
+ var value = "QtWebEngineCookieTest"
+ document.cookie = generateCookieString(name, value, {})
+
+ name = "CookieWithExpiresField"
+ value = "QtWebEngineCookieTest"
+ var daysValid = 10;
+ var date = new Date();
+ date.setTime(date.getTime() + (daysValid*24*60*60*1000));
+ var expires = date;
+ var options = {};
+ options.expires = expires;
+ document.cookie = generateCookieString(name, value, options)
+}
+</script>
+ </head>
+ <body onload="setCookie()">
+ </body>
+</html>
diff --git a/tests/auto/core/qwebenginecookiestoreclient/tst_qwebenginecookiestoreclient.cpp b/tests/auto/core/qwebenginecookiestoreclient/tst_qwebenginecookiestoreclient.cpp
new file mode 100644
index 000000000..d78a81c21
--- /dev/null
+++ b/tests/auto/core/qwebenginecookiestoreclient/tst_qwebenginecookiestoreclient.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../../widgets/util.h"
+#include <QtTest/QtTest>
+#include <QtWebEngineCore/qwebenginecallback.h>
+#include <QtWebEngineCore/qwebenginecookiestoreclient.h>
+#include <QtWebEngineWidgets/qwebenginepage.h>
+#include <QtWebEngineWidgets/qwebengineprofile.h>
+#include <QtWebEngineWidgets/qwebengineview.h>
+
+class tst_QWebEngineCookieStoreClient : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWebEngineCookieStoreClient();
+ ~tst_QWebEngineCookieStoreClient();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void cookieSignals();
+ void setAndDeleteCookie();
+ void batchCookieTasks();
+};
+
+tst_QWebEngineCookieStoreClient::tst_QWebEngineCookieStoreClient()
+{
+}
+
+tst_QWebEngineCookieStoreClient::~tst_QWebEngineCookieStoreClient()
+{
+}
+
+void tst_QWebEngineCookieStoreClient::init()
+{
+}
+
+void tst_QWebEngineCookieStoreClient::cleanup()
+{
+}
+
+void tst_QWebEngineCookieStoreClient::initTestCase()
+{
+}
+
+void tst_QWebEngineCookieStoreClient::cleanupTestCase()
+{
+}
+
+void tst_QWebEngineCookieStoreClient::cookieSignals()
+{
+ QWebEngineView view;
+ QWebEngineCookieStoreClient *client = view.page()->profile()->cookieStoreClient();
+
+ QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
+ QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
+
+ view.load(QUrl("qrc:///resources/index.html"));
+
+ QTRY_COMPARE(loadSpy.count(), 1);
+ QVariant success = loadSpy.takeFirst().takeFirst();
+ QVERIFY(success.toBool());
+ QTRY_COMPARE(cookieAddedSpy.count(), 2);
+
+ // try whether updating a cookie to be expired results in that cookie being removed.
+ QNetworkCookie expiredCookie(QNetworkCookie::parseCookies(QByteArrayLiteral("SessionCookie=delete; expires=Thu, 01-Jan-1970 00:00:00 GMT; path=///resources")).first());
+ client->setCookie(expiredCookie, QUrl("qrc:///resources/index.html"));
+ QTRY_COMPARE(cookieRemovedSpy.count(), 1);
+ cookieRemovedSpy.clear();
+
+ // try removing the other cookie.
+ QNetworkCookie nonSessionCookie(QNetworkCookie::parseCookies(QByteArrayLiteral("CookieWithExpiresField=QtWebEngineCookieTest; path=///resources")).first());
+ client->deleteCookie(nonSessionCookie, QUrl("qrc:///resources/index.html"));
+ QTRY_COMPARE(cookieRemovedSpy.count(), 1);
+}
+
+void tst_QWebEngineCookieStoreClient::setAndDeleteCookie()
+{
+ QWebEngineView view;
+ QWebEngineCookieStoreClient *client = view.page()->profile()->cookieStoreClient();
+
+ QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
+ QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
+
+ QNetworkCookie cookie1(QNetworkCookie::parseCookies(QByteArrayLiteral("khaos=I9GX8CWI; Domain=.example.com; Path=/docs")).first());
+ QNetworkCookie cookie2(QNetworkCookie::parseCookies(QByteArrayLiteral("Test%20Cookie=foobar; domain=example.com; Path=/")).first());
+ QNetworkCookie cookie3(QNetworkCookie::parseCookies(QByteArrayLiteral("SessionCookie=QtWebEngineCookieTest; Path=///resources")).first());
+ QNetworkCookie expiredCookie3(QNetworkCookie::parseCookies(QByteArrayLiteral("SessionCookie=delete; expires=Thu, 01-Jan-1970 00:00:00 GMT; path=///resources")).first());
+
+ // check if pending cookies are set and removed
+ client->setCookieWithCallback(cookie1, [](bool success) { QVERIFY(success); });
+ client->setCookieWithCallback(cookie2, [](bool success) { QVERIFY(success); });
+ client->deleteCookie(cookie1);
+
+ view.load(QUrl("qrc:///resources/content.html"));
+
+ QTRY_COMPARE(loadSpy.count(), 1);
+ QVariant success = loadSpy.takeFirst().takeFirst();
+ QVERIFY(success.toBool());
+ QTRY_COMPARE(cookieAddedSpy.count(), 2);
+ QTRY_COMPARE(cookieRemovedSpy.count(), 1);
+ cookieAddedSpy.clear();
+ cookieRemovedSpy.clear();
+
+ client->setCookieWithCallback(cookie3, [](bool success) { QVERIFY(success); });
+ // updating a cookie with an expired 'expires' field should remove the cookie with the same name
+ client->setCookieWithCallback(expiredCookie3, [](bool success) { QVERIFY(success); });
+ client->deleteCookie(cookie2);
+ QTRY_COMPARE(cookieAddedSpy.count(), 1);
+ QTRY_COMPARE(cookieRemovedSpy.count(), 2);
+}
+
+void tst_QWebEngineCookieStoreClient::batchCookieTasks()
+{
+ QWebEngineView view;
+ QWebEngineCookieStoreClient *client = view.page()->profile()->cookieStoreClient();
+
+ QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
+ QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
+
+ QNetworkCookie cookie1(QNetworkCookie::parseCookies(QByteArrayLiteral("khaos=I9GX8CWI; Domain=.example.com; Path=/docs")).first());
+ QNetworkCookie cookie2(QNetworkCookie::parseCookies(QByteArrayLiteral("Test%20Cookie=foobar; domain=example.com; Path=/")).first());
+
+ int capture = 0;
+
+ client->setCookieWithCallback(cookie1, [&capture](bool success) { QVERIFY(success); ++capture; });
+ client->setCookieWithCallback(cookie2, [&capture](bool success) { QVERIFY(success); ++capture; });
+
+ view.load(QUrl("qrc:///resources/index.html"));
+
+ QTRY_COMPARE(loadSpy.count(), 1);
+ QVariant success = loadSpy.takeFirst().takeFirst();
+ QVERIFY(success.toBool());
+ QTRY_COMPARE(cookieAddedSpy.count(), 4);
+ QTRY_COMPARE(cookieRemovedSpy.count(), 0);
+ QTRY_COMPARE(capture, 2);
+ capture = 0;
+
+ cookieAddedSpy.clear();
+ cookieRemovedSpy.clear();
+
+ client->getAllCookies([&capture](const QByteArray& cookieLine) {
+ ++capture;
+ QCOMPARE(QNetworkCookie::parseCookies(cookieLine).count(), 4);
+ });
+
+ client->deleteSessionCookiesWithCallback([&capture](int numDeleted) {
+ ++capture;
+ QCOMPARE(numDeleted, 3);
+ });
+
+ client->deleteAllCookiesWithCallback([&capture](int numDeleted) {
+ ++capture;
+ QCOMPARE(numDeleted, 1);
+ });
+
+ QTRY_COMPARE(capture, 3);
+}
+
+QTEST_MAIN(tst_QWebEngineCookieStoreClient)
+#include "tst_qwebenginecookiestoreclient.moc"
diff --git a/tests/auto/core/qwebenginecookiestoreclient/tst_qwebenginecookiestoreclient.qrc b/tests/auto/core/qwebenginecookiestoreclient/tst_qwebenginecookiestoreclient.qrc
new file mode 100644
index 000000000..afeae268b
--- /dev/null
+++ b/tests/auto/core/qwebenginecookiestoreclient/tst_qwebenginecookiestoreclient.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>resources/index.html</file>
+ <file>resources/content.html</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/qwebengineurlrequestinterceptor.pro b/tests/auto/core/qwebengineurlrequestinterceptor/qwebengineurlrequestinterceptor.pro
new file mode 100644
index 000000000..e99c7f493
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/qwebengineurlrequestinterceptor.pro
@@ -0,0 +1 @@
+include(../tests.pri)
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/content.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/content.html
new file mode 100644
index 000000000..360ad65ef
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/content.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<a>This is test content</a>
+</body>
+</html>
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/firstparty.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/firstparty.html
new file mode 100644
index 000000000..8bc540c08
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/firstparty.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<iframe src="qrc:///resources/content.html"></iframe>
+</body>
+</html>
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/index.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/index.html
new file mode 100644
index 000000000..a744dbd99
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/index.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <script type="text/javascript">
+ function post() {
+ var form = document.createElement("form");
+ form.setAttribute("method", "POST");
+ document.body.appendChild(form);
+ form.submit();
+ return true;
+ }
+</script>
+ </head>
+ <body>
+ <h1>Test page</h1>
+ </body>
+</html>
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
new file mode 100644
index 000000000..4891cafd0
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../../widgets/util.h"
+#include <QtTest/QtTest>
+#include <QtWebEngineCore/qwebengineurlrequestinterceptor.h>
+#include <QtWebEngineWidgets/qwebenginepage.h>
+#include <QtWebEngineWidgets/qwebengineprofile.h>
+#include <QtWebEngineWidgets/qwebenginesettings.h>
+#include <QtWebEngineWidgets/qwebengineview.h>
+
+class tst_QWebEngineUrlRequestInterceptor : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWebEngineUrlRequestInterceptor();
+ ~tst_QWebEngineUrlRequestInterceptor();
+
+public Q_SLOTS:
+ void init();
+ void cleanup();
+
+private Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+ void interceptRequest();
+ void ipv6HostEncoding();
+ void requestedUrl();
+ void setUrlSameUrl();
+ void firstPartyUrl();
+};
+
+tst_QWebEngineUrlRequestInterceptor::tst_QWebEngineUrlRequestInterceptor()
+{
+}
+
+tst_QWebEngineUrlRequestInterceptor::~tst_QWebEngineUrlRequestInterceptor()
+{
+}
+
+void tst_QWebEngineUrlRequestInterceptor::init()
+{
+}
+
+void tst_QWebEngineUrlRequestInterceptor::cleanup()
+{
+}
+
+void tst_QWebEngineUrlRequestInterceptor::initTestCase()
+{
+}
+
+void tst_QWebEngineUrlRequestInterceptor::cleanupTestCase()
+{
+}
+
+class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor
+{
+public:
+ QList<QUrl> observedUrls;
+ QList<QUrl> firstPartyUrls;
+ bool shouldIntercept;
+
+ bool interceptRequest(QWebEngineUrlRequestInfo &info) override
+ {
+ info.block(info.requestMethod() != QByteArrayLiteral("GET"));
+ if (info.requestUrl().toString().endsWith(QLatin1String("__placeholder__")))
+ info.redirect(QUrl("qrc:///resources/content.html"));
+
+ observedUrls.append(info.requestUrl());
+ firstPartyUrls.append(info.firstPartyUrl());
+ return shouldIntercept;
+ }
+ TestRequestInterceptor(bool intercept)
+ : shouldIntercept(intercept)
+ {
+ }
+};
+
+void tst_QWebEngineUrlRequestInterceptor::interceptRequest()
+{
+ QWebEngineView view;
+ TestRequestInterceptor interceptor(/* intercept */ true);
+
+ QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ view.page()->profile()->setRequestInterceptor(&interceptor);
+ view.load(QUrl("qrc:///resources/index.html"));
+ QTRY_COMPARE(loadSpy.count(), 1);
+ QVariant success = loadSpy.takeFirst().takeFirst();
+ QVERIFY(success.toBool());
+ loadSpy.clear();
+ QVariant ok;
+
+ view.page()->runJavaScript("post();", [&ok](const QVariant result){ ok = result; });
+ QTRY_VERIFY(ok.toBool());
+ QTRY_COMPARE(loadSpy.count(), 1);
+ success = loadSpy.takeFirst().takeFirst();
+ // We block non-GET requests, so this should not succeed.
+ QVERIFY(!success.toBool());
+ loadSpy.clear();
+
+ view.load(QUrl("qrc:///resources/__placeholder__"));
+ QTRY_COMPARE(loadSpy.count(), 1);
+ success = loadSpy.takeFirst().takeFirst();
+ // The redirection for __placeholder__ should succeed.
+ QVERIFY(success.toBool());
+ loadSpy.clear();
+ QCOMPARE(interceptor.observedUrls.count(), 4);
+
+
+ // Make sure that registering an observer does not modify the request.
+ TestRequestInterceptor observer(/* intercept */ false);
+ view.page()->profile()->setRequestInterceptor(&observer);
+ view.load(QUrl("qrc:///resources/__placeholder__"));
+ QTRY_COMPARE(loadSpy.count(), 1);
+ success = loadSpy.takeFirst().takeFirst();
+ // Since we do not intercept, loading an invalid path should not succeed.
+ QVERIFY(!success.toBool());
+ QCOMPARE(observer.observedUrls.count(), 1);
+}
+
+class LocalhostContentProvider : public QWebEngineUrlRequestInterceptor
+{
+public:
+ LocalhostContentProvider() { }
+
+ bool interceptRequest(QWebEngineUrlRequestInfo &info) override
+ {
+ requestedUrls.append(info.requestUrl());
+ info.redirect(QUrl("data:text/html,<p>hello"));
+ return true;
+ }
+
+ QList<QUrl> requestedUrls;
+};
+
+void tst_QWebEngineUrlRequestInterceptor::ipv6HostEncoding()
+{
+ QWebEngineView view;
+ QWebEnginePage *page = view.page();
+ LocalhostContentProvider contentProvider;
+ QSignalSpy spyLoadFinished(page, SIGNAL(loadFinished(bool)));
+
+ page->profile()->setRequestInterceptor(&contentProvider);
+
+ page->setHtml("<p>Hi", QUrl::fromEncoded("http://[::1]/index.html"));
+ QTRY_COMPARE(spyLoadFinished.count(), 1);
+ QCOMPARE(contentProvider.requestedUrls.count(), 0);
+
+ evaluateJavaScriptSync(page, "var r = new XMLHttpRequest();"
+ "r.open('GET', 'http://[::1]/test.xml', false);"
+ "r.send(null);"
+ );
+
+ QCOMPARE(contentProvider.requestedUrls.count(), 1);
+ QCOMPARE(contentProvider.requestedUrls.at(0), QUrl::fromEncoded("http://[::1]/test.xml"));
+}
+
+void tst_QWebEngineUrlRequestInterceptor::requestedUrl()
+{
+ QWebEnginePage page;
+ page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+
+ QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
+ TestRequestInterceptor interceptor(/* intercept */ true);
+ page.profile()->setRequestInterceptor(&interceptor);
+
+ page.setUrl(QUrl("qrc:///resources/__placeholder__"));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(interceptor.observedUrls.at(0), QUrl("qrc:///resources/content.html"));
+ QCOMPARE(page.requestedUrl(), QUrl("qrc:///resources/__placeholder__"));
+ QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
+
+ page.setUrl(QUrl("qrc:/non-existent.html"));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(interceptor.observedUrls.at(2), QUrl("qrc:/non-existent.html"));
+ QCOMPARE(page.requestedUrl(), QUrl("qrc:///resources/__placeholder__"));
+ QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
+
+ page.setUrl(QUrl("http://abcdef.abcdef"));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(spy.count(), 3);
+ QCOMPARE(interceptor.observedUrls.at(3), QUrl("http://abcdef.abcdef/"));
+ QCOMPARE(page.requestedUrl(), QUrl("qrc:///resources/__placeholder__"));
+ QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
+}
+
+void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl()
+{
+ QWebEnginePage page;
+ TestRequestInterceptor interceptor(/* intercept */ true);
+ page.profile()->setRequestInterceptor(&interceptor);
+
+ QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
+
+ page.setUrl(QUrl("qrc:///resources/__placeholder__"));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
+ QCOMPARE(spy.count(), 1);
+
+ page.setUrl(QUrl("qrc:///resources/__placeholder__"));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
+ QCOMPARE(spy.count(), 2);
+
+ // Now a case without redirect.
+ page.setUrl(QUrl("qrc:///resources/content.html"));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
+ QCOMPARE(spy.count(), 3);
+
+ page.setUrl(QUrl("qrc:///resources/__placeholder__"));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
+ QCOMPARE(spy.count(), 4);
+}
+
+void tst_QWebEngineUrlRequestInterceptor::firstPartyUrl()
+{
+ QWebEnginePage page;
+ TestRequestInterceptor interceptor(/* intercept */ false);
+ page.profile()->setRequestInterceptor(&interceptor);
+
+ QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
+
+ page.setUrl(QUrl("qrc:///resources/firstparty.html"));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(interceptor.observedUrls.at(0), QUrl("qrc:///resources/firstparty.html"));
+ QCOMPARE(interceptor.observedUrls.at(1), QUrl("qrc:///resources/content.html"));
+ QCOMPARE(interceptor.firstPartyUrls.at(0), QUrl("qrc:///resources/firstparty.html"));
+ QCOMPARE(interceptor.firstPartyUrls.at(1), QUrl("qrc:///resources/firstparty.html"));
+ QCOMPARE(spy.count(), 1);
+}
+
+QTEST_MAIN(tst_QWebEngineUrlRequestInterceptor)
+#include "tst_qwebengineurlrequestinterceptor.moc"
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc
new file mode 100644
index 000000000..ca045e7fc
--- /dev/null
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>resources/index.html</file>
+ <file>resources/content.html</file>
+ <file>resources/firstparty.html</file>
+</qresource>
+</RCC>
diff --git a/tests/auto/core/tests.pri b/tests/auto/core/tests.pri
new file mode 100644
index 000000000..cd6ef8615
--- /dev/null
+++ b/tests/auto/core/tests.pri
@@ -0,0 +1,17 @@
+TEMPLATE = app
+
+# FIXME: Re-enable once we want to run tests on the CI
+# CONFIG += testcase
+
+CONFIG += c++11
+
+VPATH += $$_PRO_FILE_PWD_
+TARGET = tst_$$TARGET
+
+SOURCES += $${TARGET}.cpp
+INCLUDEPATH += $$PWD
+
+exists($$_PRO_FILE_PWD_/$${TARGET}.qrc): RESOURCES += $${TARGET}.qrc
+
+QT += testlib network webenginewidgets widgets
+osx: CONFIG -= app_bundle
diff --git a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp
index 28a77d8cd..b5894a248 100644
--- a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp
+++ b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp
@@ -86,7 +86,7 @@ void tst_InspectorServer::prepareWebViewComponent()
m_component.reset(new QQmlComponent(engine, this));
m_component->setData(QByteArrayLiteral("import QtQuick 2.0\n"
- "import QtWebEngine 1.1\n"
+ "import QtWebEngine 1.2\n"
"WebEngineView { }")
, QUrl());
}
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index 8f0c2f6ec..bf0192e42 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -56,6 +56,7 @@
#include <private/qquickwebengineprofile_p.h>
#include <private/qquickwebenginescript_p.h>
#include <private/qquickwebenginesettings_p.h>
+#include <private/qquickwebenginesingleton_p.h>
class tst_publicapi : public QObject {
Q_OBJECT
@@ -76,6 +77,7 @@ static QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *>()
<< &QQuickWebEngineScript::staticMetaObject
<< &QQuickWebEngineSettings::staticMetaObject
<< &QQuickWebEngineFullScreenRequest::staticMetaObject
+ << &QQuickWebEngineSingleton::staticMetaObject
;
static QList<const char *> knownEnumNames = QList<const char *>();
@@ -87,28 +89,22 @@ static QStringList hardcodedTypes = QStringList()
// Ignore the testSupport types without making a fuss.
<< "QQuickWebEngineTestSupport*"
<< "QQuickWebEngineErrorPage*"
+ << "QWebEngineCookieStoreClient*"
;
static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.AcceptRequest --> NavigationRequestAction"
<< "QQuickWebEngineView.IgnoreRequest --> NavigationRequestAction"
+ << "QQuickWebEngineView.LinkClickedNavigation --> NavigationType"
+ << "QQuickWebEngineView.TypedNavigation --> NavigationType"
+ << "QQuickWebEngineView.FormSubmittedNavigation --> NavigationType"
+ << "QQuickWebEngineView.BackForwardNavigation --> NavigationType"
+ << "QQuickWebEngineView.ReloadNavigation --> NavigationType"
+ << "QQuickWebEngineView.OtherNavigation --> NavigationType"
<< "QQuickWebEngineView.LoadStartedStatus --> LoadStatus"
<< "QQuickWebEngineView.LoadStoppedStatus --> LoadStatus"
<< "QQuickWebEngineView.LoadSucceededStatus --> LoadStatus"
<< "QQuickWebEngineView.LoadFailedStatus --> LoadStatus"
- << "QQuickWebEngineCertificateError.SslPinnedKeyNotInCertificateChain --> Error"
- << "QQuickWebEngineCertificateError.CertificateCommonNameInvalid --> Error"
- << "QQuickWebEngineCertificateError.CertificateDateInvalid --> Error"
- << "QQuickWebEngineCertificateError.CertificateAuthorityInvalid --> Error"
- << "QQuickWebEngineCertificateError.CertificateContainsErrors --> Error"
- << "QQuickWebEngineCertificateError.CertificateNoRevocationMechanism --> Error"
- << "QQuickWebEngineCertificateError.CertificateUnableToCheckRevocation --> Error"
- << "QQuickWebEngineCertificateError.CertificateRevoked --> Error"
- << "QQuickWebEngineCertificateError.CertificateInvalid --> Error"
- << "QQuickWebEngineCertificateError.CertificateWeakSignatureAlgorithm --> Error"
- << "QQuickWebEngineCertificateError.CertificateNonUniqueName --> Error"
- << "QQuickWebEngineCertificateError.CertificateWeakKey --> Error"
- << "QQuickWebEngineCertificateError.CertificateNameConstraintViolation --> Error"
<< "QQuickWebEngineView.NoErrorDomain --> ErrorDomain"
<< "QQuickWebEngineView.InternalErrorDomain --> ErrorDomain"
<< "QQuickWebEngineView.ConnectionErrorDomain --> ErrorDomain"
@@ -116,14 +112,6 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.HttpErrorDomain --> ErrorDomain"
<< "QQuickWebEngineView.FtpErrorDomain --> ErrorDomain"
<< "QQuickWebEngineView.DnsErrorDomain --> ErrorDomain"
- << "QQuickWebEngineView.FindBackward --> FindFlags"
- << "QQuickWebEngineView.FindCaseSensitively --> FindFlags"
- << "QQuickWebEngineView.LinkClickedNavigation --> NavigationType"
- << "QQuickWebEngineView.TypedNavigation --> NavigationType"
- << "QQuickWebEngineView.FormSubmittedNavigation --> NavigationType"
- << "QQuickWebEngineView.BackForwardNavigation --> NavigationType"
- << "QQuickWebEngineView.ReloadNavigation --> NavigationType"
- << "QQuickWebEngineView.OtherNavigation --> NavigationType"
<< "QQuickWebEngineView.NewViewInWindow --> NewViewDestination"
<< "QQuickWebEngineView.NewViewInTab --> NewViewDestination"
<< "QQuickWebEngineView.NewViewInDialog --> NewViewDestination"
@@ -132,31 +120,81 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.MediaVideoCapture --> Feature"
<< "QQuickWebEngineView.MediaAudioVideoCapture --> Feature"
<< "QQuickWebEngineView.Geolocation --> Feature"
+ << "QQuickWebEngineView.NoWebAction --> WebAction"
+ << "QQuickWebEngineView.Back --> WebAction"
+ << "QQuickWebEngineView.Forward --> WebAction"
+ << "QQuickWebEngineView.Stop --> WebAction"
+ << "QQuickWebEngineView.Reload --> WebAction"
+ << "QQuickWebEngineView.Cut --> WebAction"
+ << "QQuickWebEngineView.Copy --> WebAction"
+ << "QQuickWebEngineView.Paste --> WebAction"
+ << "QQuickWebEngineView.Undo --> WebAction"
+ << "QQuickWebEngineView.Redo --> WebAction"
+ << "QQuickWebEngineView.SelectAll --> WebAction"
+ << "QQuickWebEngineView.ReloadAndBypassCache --> WebAction"
+ << "QQuickWebEngineView.PasteAndMatchStyle --> WebAction"
+ << "QQuickWebEngineView.OpenLinkInThisWindow --> WebAction"
+ << "QQuickWebEngineView.OpenLinkInNewWindow --> WebAction"
+ << "QQuickWebEngineView.OpenLinkInNewTab --> WebAction"
+ << "QQuickWebEngineView.CopyLinkToClipboard --> WebAction"
+ << "QQuickWebEngineView.DownloadLinkToDisk --> WebAction"
+ << "QQuickWebEngineView.CopyImageToClipboard --> WebAction"
+ << "QQuickWebEngineView.CopyImageUrlToClipboard --> WebAction"
+ << "QQuickWebEngineView.DownloadImageToDisk --> WebAction"
+ << "QQuickWebEngineView.CopyMediaUrlToClipboard --> WebAction"
+ << "QQuickWebEngineView.ToggleMediaControls --> WebAction"
+ << "QQuickWebEngineView.ToggleMediaLoop --> WebAction"
+ << "QQuickWebEngineView.ToggleMediaPlayPause --> WebAction"
+ << "QQuickWebEngineView.ToggleMediaMute --> WebAction"
+ << "QQuickWebEngineView.DownloadMediaToDisk --> WebAction"
+ << "QQuickWebEngineView.InspectElement --> WebAction"
+ << "QQuickWebEngineView.ExitFullScreen --> WebAction"
+ << "QQuickWebEngineView.WebActionCount --> WebAction"
<< "QQuickWebEngineView.InfoMessageLevel --> JavaScriptConsoleMessageLevel"
<< "QQuickWebEngineView.WarningMessageLevel --> JavaScriptConsoleMessageLevel"
<< "QQuickWebEngineView.ErrorMessageLevel --> JavaScriptConsoleMessageLevel"
- << "QQuickWebEngineView.title --> QString"
+ << "QQuickWebEngineView.NormalTerminationStatus --> RenderProcessTerminationStatus"
+ << "QQuickWebEngineView.AbnormalTerminationStatus --> RenderProcessTerminationStatus"
+ << "QQuickWebEngineView.CrashedTerminationStatus --> RenderProcessTerminationStatus"
+ << "QQuickWebEngineView.KilledTerminationStatus --> RenderProcessTerminationStatus"
+ << "QQuickWebEngineView.FindBackward --> FindFlags"
+ << "QQuickWebEngineView.FindCaseSensitively --> FindFlags"
<< "QQuickWebEngineView.url --> QUrl"
<< "QQuickWebEngineView.icon --> QUrl"
+ << "QQuickWebEngineView.loading --> bool"
+ << "QQuickWebEngineView.loadProgress --> int"
+ << "QQuickWebEngineView.title --> QString"
<< "QQuickWebEngineView.canGoBack --> bool"
<< "QQuickWebEngineView.canGoForward --> bool"
<< "QQuickWebEngineView.isFullScreen --> bool"
- << "QQuickWebEngineView.loading --> bool"
- << "QQuickWebEngineView.loadProgress --> int"
+ << "QQuickWebEngineView.zoomFactor --> double"
+ << "QQuickWebEngineView.profile --> QQuickWebEngineProfile*"
+ << "QQuickWebEngineView.settings --> QQuickWebEngineSettings*"
+ << "QQuickWebEngineView.navigationHistory --> QQuickWebEngineHistory*"
+ << "QQuickWebEngineView.webChannel --> QQmlWebChannel*"
+ << "QQuickWebEngineView.userScripts --> QQmlListProperty<QQuickWebEngineScript>"
+ << "QQuickWebEngineView.activeFocusOnPress --> bool"
+ << "QQuickWebEngineView.backgroundColor --> QColor"
+ << "QQuickWebEngineView.testSupport --> QQuickWebEngineTestSupport*"
<< "QQuickWebEngineView.titleChanged() --> void"
- << "QQuickWebEngineView.loadingChanged(QQuickWebEngineLoadRequest*) --> void"
- << "QQuickWebEngineView.certificateError(QQuickWebEngineCertificateError*) --> void"
- << "QQuickWebEngineView.loadProgressChanged() --> void"
- << "QQuickWebEngineView.javaScriptConsoleMessage(JavaScriptConsoleMessageLevel,QString,int,QString) --> void"
<< "QQuickWebEngineView.urlChanged() --> void"
<< "QQuickWebEngineView.iconChanged() --> void"
+ << "QQuickWebEngineView.loadingChanged(QQuickWebEngineLoadRequest*) --> void"
+ << "QQuickWebEngineView.loadProgressChanged() --> void"
<< "QQuickWebEngineView.linkHovered(QUrl) --> void"
<< "QQuickWebEngineView.navigationRequested(QQuickWebEngineNavigationRequest*) --> void"
+ << "QQuickWebEngineView.javaScriptConsoleMessage(JavaScriptConsoleMessageLevel,QString,int,QString) --> void"
+ << "QQuickWebEngineView.certificateError(QQuickWebEngineCertificateError*) --> void"
<< "QQuickWebEngineView.fullScreenRequested(QQuickWebEngineFullScreenRequest) --> void"
<< "QQuickWebEngineView.isFullScreenChanged() --> void"
- << "QQuickWebEngineView.fullScreenCancelled() --> void"
<< "QQuickWebEngineView.featurePermissionRequested(QUrl,Feature) --> void"
- << "QQuickWebEngineView.grantFeaturePermission(QUrl,Feature,bool) --> void"
+ << "QQuickWebEngineView.newViewRequested(QQuickWebEngineNewViewRequest*) --> void"
+ << "QQuickWebEngineView.zoomFactorChanged(double) --> void"
+ << "QQuickWebEngineView.profileChanged() --> void"
+ << "QQuickWebEngineView.webChannelChanged() --> void"
+ << "QQuickWebEngineView.activeFocusOnPressChanged(bool) --> void"
+ << "QQuickWebEngineView.backgroundColorChanged() --> void"
+ << "QQuickWebEngineView.renderProcessTerminated(RenderProcessTerminationStatus,int) --> void"
<< "QQuickWebEngineView.runJavaScript(QString,QJSValue) --> void"
<< "QQuickWebEngineView.runJavaScript(QString) --> void"
<< "QQuickWebEngineView.loadHtml(QString,QUrl) --> void"
@@ -164,37 +202,50 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.goBack() --> void"
<< "QQuickWebEngineView.goForward() --> void"
<< "QQuickWebEngineView.goBackOrForward(int) --> void"
- << "QQuickWebEngineView.stop() --> void"
<< "QQuickWebEngineView.reload() --> void"
- << "QQuickWebEngineView.zoomFactor --> double"
- << "QQuickWebEngineView.zoomFactorChanged(double) --> void"
- << "QQuickWebEngineView.profile --> QQuickWebEngineProfile*"
- << "QQuickWebEngineView.profileChanged() --> void"
- << "QQuickWebEngineView.navigationHistory --> QQuickWebEngineHistory*"
- << "QQuickWebEngineView.newViewRequested(QQuickWebEngineNewViewRequest*) --> void"
- << "QQuickWebEngineView.userScripts --> QQmlListProperty<QQuickWebEngineScript>"
- << "QQuickWebEngineView.settings --> QQuickWebEngineSettings*"
- << "QQuickWebEngineView.testSupport --> QQuickWebEngineTestSupport*"
- << "QQuickWebEngineView.webChannel --> QQmlWebChannel*"
- << "QQuickWebEngineView.webChannelChanged() --> void"
<< "QQuickWebEngineView.reloadAndBypassCache() --> void"
+ << "QQuickWebEngineView.stop() --> void"
<< "QQuickWebEngineView.findText(QString,FindFlags,QJSValue) --> void"
<< "QQuickWebEngineView.findText(QString,FindFlags) --> void"
<< "QQuickWebEngineView.findText(QString) --> void"
- << "QQuickWebEngineDownloadItem.id --> uint"
- << "QQuickWebEngineDownloadItem.state --> DownloadState"
- << "QQuickWebEngineDownloadItem.path --> QString"
- << "QQuickWebEngineDownloadItem.totalBytes --> qlonglong"
- << "QQuickWebEngineDownloadItem.receivedBytes --> qlonglong"
+ << "QQuickWebEngineView.fullScreenCancelled() --> void"
+ << "QQuickWebEngineView.grantFeaturePermission(QUrl,Feature,bool) --> void"
+ << "QQuickWebEngineView.setActiveFocusOnPress(bool) --> void"
+ << "QQuickWebEngineView.triggerWebAction(WebAction) --> void"
+ << "QQuickWebEngineCertificateError.SslPinnedKeyNotInCertificateChain --> Error"
+ << "QQuickWebEngineCertificateError.CertificateCommonNameInvalid --> Error"
+ << "QQuickWebEngineCertificateError.CertificateDateInvalid --> Error"
+ << "QQuickWebEngineCertificateError.CertificateAuthorityInvalid --> Error"
+ << "QQuickWebEngineCertificateError.CertificateContainsErrors --> Error"
+ << "QQuickWebEngineCertificateError.CertificateNoRevocationMechanism --> Error"
+ << "QQuickWebEngineCertificateError.CertificateUnableToCheckRevocation --> Error"
+ << "QQuickWebEngineCertificateError.CertificateRevoked --> Error"
+ << "QQuickWebEngineCertificateError.CertificateInvalid --> Error"
+ << "QQuickWebEngineCertificateError.CertificateWeakSignatureAlgorithm --> Error"
+ << "QQuickWebEngineCertificateError.CertificateNonUniqueName --> Error"
+ << "QQuickWebEngineCertificateError.CertificateWeakKey --> Error"
+ << "QQuickWebEngineCertificateError.CertificateNameConstraintViolation --> Error"
+ << "QQuickWebEngineCertificateError.url --> QUrl"
+ << "QQuickWebEngineCertificateError.error --> Error"
+ << "QQuickWebEngineCertificateError.description --> QString"
+ << "QQuickWebEngineCertificateError.overridable --> bool"
+ << "QQuickWebEngineCertificateError.defer() --> void"
+ << "QQuickWebEngineCertificateError.ignoreCertificateError() --> void"
+ << "QQuickWebEngineCertificateError.rejectCertificate() --> void"
<< "QQuickWebEngineDownloadItem.DownloadRequested --> DownloadState"
<< "QQuickWebEngineDownloadItem.DownloadInProgress --> DownloadState"
<< "QQuickWebEngineDownloadItem.DownloadCompleted --> DownloadState"
<< "QQuickWebEngineDownloadItem.DownloadCancelled --> DownloadState"
<< "QQuickWebEngineDownloadItem.DownloadInterrupted --> DownloadState"
+ << "QQuickWebEngineDownloadItem.id --> uint"
+ << "QQuickWebEngineDownloadItem.state --> DownloadState"
+ << "QQuickWebEngineDownloadItem.totalBytes --> qlonglong"
+ << "QQuickWebEngineDownloadItem.receivedBytes --> qlonglong"
+ << "QQuickWebEngineDownloadItem.path --> QString"
<< "QQuickWebEngineDownloadItem.stateChanged() --> void"
- << "QQuickWebEngineDownloadItem.pathChanged() --> void"
<< "QQuickWebEngineDownloadItem.receivedBytesChanged() --> void"
<< "QQuickWebEngineDownloadItem.totalBytesChanged() --> void"
+ << "QQuickWebEngineDownloadItem.pathChanged() --> void"
<< "QQuickWebEngineDownloadItem.accept() --> void"
<< "QQuickWebEngineDownloadItem.cancel() --> void"
<< "QQuickWebEngineHistory.items --> QQuickWebEngineHistoryListModel*"
@@ -224,6 +275,7 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineProfile.cachePath --> QString"
<< "QQuickWebEngineProfile.httpUserAgent --> QString"
<< "QQuickWebEngineProfile.httpCacheType --> HttpCacheType"
+ << "QQuickWebEngineProfile.httpAcceptLanguage --> QString"
<< "QQuickWebEngineProfile.persistentCookiesPolicy --> PersistentCookiesPolicy"
<< "QQuickWebEngineProfile.httpCacheMaximumSize --> int"
<< "QQuickWebEngineProfile.storageNameChanged() --> void"
@@ -234,39 +286,10 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineProfile.httpCacheTypeChanged() --> void"
<< "QQuickWebEngineProfile.persistentCookiesPolicyChanged() --> void"
<< "QQuickWebEngineProfile.httpCacheMaximumSizeChanged() --> void"
+ << "QQuickWebEngineProfile.httpAcceptLanguageChanged() --> void"
<< "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadItem*) --> void"
<< "QQuickWebEngineProfile.downloadFinished(QQuickWebEngineDownloadItem*) --> void"
- << "QQuickWebEngineSettings.autoLoadImages --> bool"
- << "QQuickWebEngineSettings.javascriptEnabled --> bool"
- << "QQuickWebEngineSettings.javascriptCanOpenWindows --> bool"
- << "QQuickWebEngineSettings.javascriptCanAccessClipboard --> bool"
- << "QQuickWebEngineSettings.linksIncludedInFocusChain --> bool"
- << "QQuickWebEngineSettings.localStorageEnabled --> bool"
- << "QQuickWebEngineSettings.localContentCanAccessRemoteUrls --> bool"
- << "QQuickWebEngineSettings.spatialNavigationEnabled --> bool"
- << "QQuickWebEngineSettings.localContentCanAccessFileUrls --> bool"
- << "QQuickWebEngineSettings.hyperlinkAuditingEnabled --> bool"
- << "QQuickWebEngineSettings.errorPageEnabled --> bool"
- << "QQuickWebEngineSettings.defaultTextEncoding --> QString"
- << "QQuickWebEngineSettings.autoLoadImagesChanged() --> void"
- << "QQuickWebEngineSettings.javascriptEnabledChanged() --> void"
- << "QQuickWebEngineSettings.javascriptCanOpenWindowsChanged() --> void"
- << "QQuickWebEngineSettings.javascriptCanAccessClipboardChanged() --> void"
- << "QQuickWebEngineSettings.linksIncludedInFocusChainChanged() --> void"
- << "QQuickWebEngineSettings.localStorageEnabledChanged() --> void"
- << "QQuickWebEngineSettings.localContentCanAccessRemoteUrlsChanged() --> void"
- << "QQuickWebEngineSettings.spatialNavigationEnabledChanged() --> void"
- << "QQuickWebEngineSettings.localContentCanAccessFileUrlsChanged() --> void"
- << "QQuickWebEngineSettings.hyperlinkAuditingEnabledChanged() --> void"
- << "QQuickWebEngineSettings.errorPageEnabledChanged() --> void"
- << "QQuickWebEngineSettings.defaultTextEncodingChanged() --> void"
- << "QQuickWebEngineCertificateError.ignoreCertificateError() --> void"
- << "QQuickWebEngineCertificateError.rejectCertificate() --> void"
- << "QQuickWebEngineCertificateError.defer() --> void"
- << "QQuickWebEngineCertificateError.url --> QUrl"
- << "QQuickWebEngineCertificateError.error --> Error"
- << "QQuickWebEngineCertificateError.description --> QString"
- << "QQuickWebEngineCertificateError.overridable --> bool"
+ << "QQuickWebEngineProfile.setCookieStoreClient(QWebEngineCookieStoreClient*) --> void"
<< "QQuickWebEngineScript.Deferred --> InjectionPoint"
<< "QQuickWebEngineScript.DocumentReady --> InjectionPoint"
<< "QQuickWebEngineScript.DocumentCreation --> InjectionPoint"
@@ -292,8 +315,38 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineScript.setWorldId(ScriptWorldId) --> void"
<< "QQuickWebEngineScript.setRunOnSubframes(bool) --> void"
<< "QQuickWebEngineScript.toString() --> QString"
+ << "QQuickWebEngineSettings.autoLoadImages --> bool"
+ << "QQuickWebEngineSettings.javascriptEnabled --> bool"
+ << "QQuickWebEngineSettings.javascriptCanOpenWindows --> bool"
+ << "QQuickWebEngineSettings.javascriptCanAccessClipboard --> bool"
+ << "QQuickWebEngineSettings.linksIncludedInFocusChain --> bool"
+ << "QQuickWebEngineSettings.localStorageEnabled --> bool"
+ << "QQuickWebEngineSettings.localContentCanAccessRemoteUrls --> bool"
+ << "QQuickWebEngineSettings.spatialNavigationEnabled --> bool"
+ << "QQuickWebEngineSettings.localContentCanAccessFileUrls --> bool"
+ << "QQuickWebEngineSettings.hyperlinkAuditingEnabled --> bool"
+ << "QQuickWebEngineSettings.errorPageEnabled --> bool"
+ << "QQuickWebEngineSettings.pluginsEnabled --> bool"
+ << "QQuickWebEngineSettings.fullScreenSupportEnabled --> bool"
+ << "QQuickWebEngineSettings.defaultTextEncoding --> QString"
+ << "QQuickWebEngineSettings.autoLoadImagesChanged() --> void"
+ << "QQuickWebEngineSettings.javascriptEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.javascriptCanOpenWindowsChanged() --> void"
+ << "QQuickWebEngineSettings.javascriptCanAccessClipboardChanged() --> void"
+ << "QQuickWebEngineSettings.linksIncludedInFocusChainChanged() --> void"
+ << "QQuickWebEngineSettings.localStorageEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.localContentCanAccessRemoteUrlsChanged() --> void"
+ << "QQuickWebEngineSettings.spatialNavigationEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.localContentCanAccessFileUrlsChanged() --> void"
+ << "QQuickWebEngineSettings.hyperlinkAuditingEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.errorPageEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.pluginsEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.fullScreenSupportEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.defaultTextEncodingChanged() --> void"
<< "QQuickWebEngineFullScreenRequest.toggleOn --> bool"
<< "QQuickWebEngineFullScreenRequest.accept() --> void"
+ << "QQuickWebEngineSingleton.settings --> QQuickWebEngineSettings*"
+ << "QQuickWebEngineSingleton.defaultProfile --> QQuickWebEngineProfile*"
;
static bool isCheckedEnum(const QByteArray &typeName)
diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
index a97739404..e2c5c9009 100644
--- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml
+++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
@@ -41,12 +41,13 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
import QtWebEngine.experimental 1.0
WebEngineView {
property var loadStatus: null
property var viewportReady: false
+ property bool windowCloseRequestedSignalEmitted: false
function waitForLoadSucceeded() {
var success = _waitFor(function() { return loadStatus == WebEngineView.LoadSucceededStatus })
@@ -69,6 +70,9 @@ WebEngineView {
loadStatus = null
return stop
}
+ function waitForWindowCloseRequested() {
+ return _waitFor(function() { return windowCloseRequestedSignalEmitted; });
+ }
function _waitFor(predicate) {
var timeout = 5000
var i = 0
@@ -87,5 +91,8 @@ WebEngineView {
viewportReady = false
}
+ onWindowCloseRequested: {
+ windowCloseRequestedSignalEmitted = true;
+ }
}
diff --git a/tests/auto/quick/qmltests/data/confirmclose.html b/tests/auto/quick/qmltests/data/confirmclose.html
new file mode 100644
index 000000000..ba11da7a4
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/confirmclose.html
@@ -0,0 +1,5 @@
+<html>
+<body onbeforeunload="return 'You are about to miss out on some awesome content.';">
+ Be greeted, precious viewer!
+</body>
+</html>
diff --git a/tests/auto/quick/qmltests/data/directoryupload.html b/tests/auto/quick/qmltests/data/directoryupload.html
new file mode 100644
index 000000000..6a6e4580c
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/directoryupload.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+<meta name="viewport" initial-scale=1">
+<title> Directory Upload </title>
+<script src = "./titleupdate.js">
+</script>
+
+<body>
+<input type="file" id="upfile" webkitdirectory="" directory="" onchange="updateTitle()">
+<script>
+window.onload = function() {
+document.getElementById("upfile").focus()
+}
+</script>
+</body>
+</html>
diff --git a/tests/auto/quick/qmltests/data/forms.html b/tests/auto/quick/qmltests/data/forms.html
new file mode 100644
index 000000000..8dc3472f2
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/forms.html
@@ -0,0 +1,40 @@
+<html>
+<head>
+ <title>Forms</title>
+ <script type="text/javascript">
+ function updateFocus() {
+ var name = window.location.hash.substring(1);
+ var element = document.getElementsByName(name)[0];
+
+ element.focus();
+ }
+ </script>
+</head>
+<body onload="updateFocus();">
+ <form>
+ <input type="url" required/>
+ <input type="submit" name="url_empty"/>
+ </form>
+ <form>
+ <input type="url" value="invalid" required/>
+ <input type="submit" name="url_invalid"/>
+ </form>
+ <form>
+ <input type="url" value="invalid" title="url_title" required/>
+ <input type="submit" name="url_title"/>
+ </form>
+
+ <form>
+ <input type="email" required/>
+ <input type="submit" name="email_empty"/>
+ </form>
+ <form>
+ <input type="email" value="invalid" required/>
+ <input type="submit" name="email_invalid"/>
+ </form>
+ <form>
+ <input type="email" value="invalid" title="email_title" required/>
+ <input type="submit" name="email_title"/>
+ </form>
+</body>
+</html>
diff --git a/tests/auto/quick/qmltests/data/multifileupload.html b/tests/auto/quick/qmltests/data/multifileupload.html
new file mode 100644
index 000000000..cc87d8f41
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/multifileupload.html
@@ -0,0 +1,17 @@
+<html>
+<head>
+<meta name="viewport" initial-scale=1">
+<title> Mutli-file Upload </title>
+<script src = "./titleupdate.js">
+</script>
+
+<body>
+<input type="file" name="file" id="upfile" onchange="updateTitle()" multiple/>
+
+<script>
+window.onload = function() {
+document.getElementById("upfile").focus()
+}
+</script>
+</body>
+</html>
diff --git a/tests/auto/quick/qmltests/data/singlefileupload.html b/tests/auto/quick/qmltests/data/singlefileupload.html
new file mode 100644
index 000000000..8469aa128
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/singlefileupload.html
@@ -0,0 +1,17 @@
+<html>
+<head>
+<meta name="viewport" initial-scale=1">
+<title> Single File Upload </title>
+<script src = "./titleupdate.js">
+</script>
+
+<body>
+<input type="file" name="file" id="upfile" onchange="updateTitle()"/>
+
+<script>
+window.onload = function() {
+document.getElementById("upfile").focus()
+}
+</script>
+</body>
+</html>
diff --git a/tests/auto/quick/qmltests/data/titleupdate.js b/tests/auto/quick/qmltests/data/titleupdate.js
new file mode 100644
index 000000000..cfcc52c60
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/titleupdate.js
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+function updateTitle()
+{
+ var inp = document.getElementById("upfile");
+ var allfiles = new String("");
+ var name = new String("");
+ for (var i = 0; i < inp.files.length; ++i) {
+ name = inp.files.item(i).name;
+ if (allfiles.length == 0)
+ allfiles = name;
+ else
+ allfiles = allfiles + "," + name;
+ }
+ document.title = allfiles;
+}
diff --git a/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml b/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml
new file mode 100644
index 000000000..eaca8822b
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_activeFocusOnPress.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtTest 1.0
+
+Item {
+ id: root
+ width: 300
+ height: 400
+ TextInput {
+ id: textInput
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ }
+ focus: true
+ text: "foo"
+ }
+
+ TestWebEngineView {
+ id: webEngineView
+ activeFocusOnPress: false
+ anchors {
+ top: textInput.bottom
+ left: parent.left
+ right: parent.right
+ bottom: parent.bottom
+ }
+
+ TestCase {
+ name: "ActiveFocusOnPress"
+ when:windowShown
+
+ function test_activeFocusOnPress() {
+ textInput.forceActiveFocus()
+ verify(textInput.activeFocus)
+ mouseClick(root, 150, 300, Qt.LeftButton)
+ verify(textInput.activeFocus)
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml b/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml
index dfb983c43..51c1d5580 100644
--- a/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml
+++ b/tests/auto/quick/qmltests/data/tst_desktopBehaviorLoadHtml.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_favIconLoad.qml b/tests/auto/quick/qmltests/data/tst_favIconLoad.qml
index 73190f1bd..df5479eec 100644
--- a/tests/auto/quick/qmltests/data/tst_favIconLoad.qml
+++ b/tests/auto/quick/qmltests/data/tst_favIconLoad.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_filePicker.qml b/tests/auto/quick/qmltests/data/tst_filePicker.qml
new file mode 100644
index 000000000..02b2dd024
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_filePicker.qml
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebEngine 1.2
+import "../mock-delegates/TestParams" 1.0
+
+TestWebEngineView {
+ id: webEngineView
+ width: 400
+ height: 300
+
+ SignalSpy {
+ id: titleSpy
+ target: webEngineView
+ signalName: "titleChanged"
+ }
+
+ TestCase {
+ name: "WebEngineViewSingleFileUpload"
+ when: windowShown
+
+ function init() {
+ FilePickerParams.filePickerOpened = false
+ FilePickerParams.selectFiles = false
+ FilePickerParams.selectedFilesUrl = []
+ titleSpy.clear()
+ }
+
+ // FIXME: Almost every second url loading progress does get stuck at about 90 percent, so the loadFinished signal won't arrive.
+ // This cleanup function is a workaround for this problem.
+ function cleanup() {
+ webEngineView.url = Qt.resolvedUrl("about:blank")
+ webEngineView.waitForLoadSucceeded()
+ }
+
+ function test_acceptSingleFileSelection() {
+ webEngineView.url = Qt.resolvedUrl("singlefileupload.html")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ FilePickerParams.selectFiles = true
+ FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("test1.html"))
+
+ keyPress(Qt.Key_Enter) // Focus is on the button. Open FileDialog.
+ wait(100) // The ui delegate is invoked asynchronously
+ verify(FilePickerParams.filePickerOpened)
+ titleSpy.wait()
+ compare(webEngineView.title, "test1.html")
+ }
+
+ function test_acceptMultipleFilesSelection() {
+ webEngineView.url = Qt.resolvedUrl("multifileupload.html")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ FilePickerParams.selectFiles = true
+ FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("test1.html"))
+ FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("test2.html"))
+
+ keyPress(Qt.Key_Enter) // Focus is on the button. Open FileDialog.
+ wait(100)
+ verify(FilePickerParams.filePickerOpened)
+ titleSpy.wait()
+ compare(webEngineView.title, "test1.html,test2.html")
+ }
+
+ function test_acceptDirectory() {
+ webEngineView.url = Qt.resolvedUrl("directoryupload.html")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ FilePickerParams.selectFiles = true
+ FilePickerParams.selectedFilesUrl.push(Qt.resolvedUrl("../data"))
+
+ keyPress(Qt.Key_Enter) // Focus is on the button. Open FileDialog.
+ wait(100) // The ui delegate is invoked asynchronously
+ verify(FilePickerParams.filePickerOpened)
+ titleSpy.wait()
+ compare(webEngineView.title, "data")
+ }
+
+ function test_reject() {
+ webEngineView.url = Qt.resolvedUrl("singlefileupload.html")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ titleSpy.clear()
+ keyPress(Qt.Key_Enter) // Focus is on the button. Open FileDialog.
+ wait(100)
+ compare(titleSpy.count, 0)
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml
index b51da0b2e..9c4aa48c1 100644
--- a/tests/auto/quick/qmltests/data/tst_findText.qml
+++ b/tests/auto/quick/qmltests/data/tst_findText.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_formValidation.qml b/tests/auto/quick/qmltests/data/tst_formValidation.qml
new file mode 100644
index 000000000..4acb7ce63
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_formValidation.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebEngine 1.2
+import QtWebEngine.testsupport 1.0
+
+TestWebEngineView {
+ id: webEngineView
+ width: 400
+ height: 300
+
+ testSupport: WebEngineTestSupport {
+ id: testSupportAPI
+ }
+
+ SignalSpy {
+ id: showSpy
+ target: testSupportAPI
+ signalName: "validationMessageShown"
+ }
+
+ TestCase {
+ name: "WebEngineViewFormValidation"
+ when: windowShown
+
+ function init() {
+ webEngineView.url = Qt.resolvedUrl("about:blank")
+ verify(webEngineView.waitForLoadSucceeded())
+ showSpy.clear()
+ }
+
+ function test_urlForm() {
+ webEngineView.url = Qt.resolvedUrl("forms.html#url_empty")
+ verify(webEngineView.waitForLoadSucceeded())
+ keyPress(Qt.Key_Enter)
+ showSpy.wait()
+ compare(showSpy.signalArguments[0][0], "Please fill out this field.")
+
+ webEngineView.url = Qt.resolvedUrl("about:blank")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ webEngineView.url = Qt.resolvedUrl("forms.html#url_invalid")
+ verify(webEngineView.waitForLoadSucceeded())
+ keyPress(Qt.Key_Enter)
+ showSpy.wait()
+ compare(showSpy.signalArguments[1][0], "Please enter a URL.")
+
+ webEngineView.url = Qt.resolvedUrl("about:blank")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ webEngineView.url = Qt.resolvedUrl("forms.html#url_title")
+ verify(webEngineView.waitForLoadSucceeded())
+ keyPress(Qt.Key_Enter)
+ showSpy.wait()
+ compare(showSpy.signalArguments[2][1], "url_title")
+ }
+
+ function test_emailForm() {
+ webEngineView.url = Qt.resolvedUrl("forms.html#email_empty")
+ verify(webEngineView.waitForLoadSucceeded())
+ keyPress(Qt.Key_Enter)
+ showSpy.wait()
+ compare(showSpy.signalArguments[0][0], "Please fill out this field.")
+
+ webEngineView.url = Qt.resolvedUrl("about:blank")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ webEngineView.url = Qt.resolvedUrl("forms.html#email_invalid")
+ verify(webEngineView.waitForLoadSucceeded())
+ keyPress(Qt.Key_Enter)
+ showSpy.wait()
+ compare(showSpy.signalArguments[1][0], "Please include an '@' in the email address. 'invalid' is missing an '@'.")
+
+ webEngineView.url = Qt.resolvedUrl("about:blank")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ webEngineView.url = Qt.resolvedUrl("forms.html#email_title")
+ verify(webEngineView.waitForLoadSucceeded())
+ keyPress(Qt.Key_Enter)
+ showSpy.wait()
+ compare(showSpy.signalArguments[2][1], "email_title")
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml b/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml
index 58a49da5a..4294c5ba3 100644
--- a/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml
+++ b/tests/auto/quick/qmltests/data/tst_javaScriptDialogs.qml
@@ -41,12 +41,27 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.0
+import QtWebEngine 1.2
+import QtWebEngine.testsupport 1.0
import "../mock-delegates/TestParams" 1.0
TestWebEngineView {
id: webEngineView
+ testSupport: WebEngineTestSupport {
+ property bool windowCloseRejectedSignalEmitted: false
+
+ function waitForWindowCloseRejected() {
+ return _waitFor(function () {
+ return testSupport.windowCloseRejectedSignalEmitted;
+ });
+ }
+
+ onWindowCloseRejected: {
+ windowCloseRejectedSignalEmitted = true;
+ }
+ }
+
TestCase {
id: test
name: "WebEngineViewJavaScriptDialogs"
@@ -80,6 +95,24 @@ TestWebEngineView {
}
+ function test_confirmClose() {
+ webEngineView.url = Qt.resolvedUrl("confirmclose.html");
+ verify(webEngineView.waitForLoadSucceeded());
+ webEngineView.windowCloseRequestedSignalEmitted = false;
+ JSDialogParams.shouldAcceptDialog = true;
+ webEngineView.triggerWebAction(WebEngineView.RequestClose);
+ verify(webEngineView.waitForWindowCloseRequested());
+ }
+
+ function test_rejectClose() {
+ webEngineView.url = Qt.resolvedUrl("confirmclose.html");
+ verify(webEngineView.waitForLoadSucceeded());
+ webEngineView.testSupport.windowCloseRejectedSignalEmitted = false;
+ JSDialogParams.shouldAcceptDialog = false;
+ webEngineView.triggerWebAction(WebEngineView.RequestClose);
+ verify(webEngineView.testSupport.waitForWindowCloseRejected());
+ }
+
function test_prompt() {
JSDialogParams.inputForPrompt = "tQ olleH"
webEngineView.url = Qt.resolvedUrl("prompt.html")
diff --git a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
index 230ee9635..c127d7391 100644
--- a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
+++ b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_linkHovered.qml b/tests/auto/quick/qmltests/data/tst_linkHovered.qml
index c9fbd5520..31d90615b 100644
--- a/tests/auto/quick/qmltests/data/tst_linkHovered.qml
+++ b/tests/auto/quick/qmltests/data/tst_linkHovered.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_loadFail.qml b/tests/auto/quick/qmltests/data/tst_loadFail.qml
index 0885fc193..c2a4b6e13 100644
--- a/tests/auto/quick/qmltests/data/tst_loadFail.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadFail.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
import QtWebEngine.experimental 1.0
import QtWebEngine.testsupport 1.0
diff --git a/tests/auto/quick/qmltests/data/tst_loadHtml.qml b/tests/auto/quick/qmltests/data/tst_loadHtml.qml
index b8acd0dd7..ee1149b16 100644
--- a/tests/auto/quick/qmltests/data/tst_loadHtml.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadHtml.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_loadProgress.qml b/tests/auto/quick/qmltests/data/tst_loadProgress.qml
index 9f8b6f6f7..096861c4d 100644
--- a/tests/auto/quick/qmltests/data/tst_loadProgress.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadProgress.qml
@@ -41,22 +41,39 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
width: 400
height: 300
+ property var loadProgressArray: []
+
+ onLoadProgressChanged: {
+ loadProgressArray.push(webEngineView.loadProgress)
+ }
+
TestCase {
name: "WebEngineViewLoadProgress"
function test_loadProgress() {
compare(webEngineView.loadProgress, 0)
+ loadProgressArray = []
+
webEngineView.url = Qt.resolvedUrl("test1.html")
- compare(webEngineView.loadProgress, 0)
verify(webEngineView.waitForLoadSucceeded())
- compare(webEngineView.loadProgress, 100)
+
+ // Test whether the chromium emits progress numbers in ascending order
+ var loadProgressMin = 0
+ for (var i in loadProgressArray) {
+ var loadProgress = loadProgressArray[i]
+ verify(loadProgressMin <= loadProgress)
+ loadProgressMin = loadProgress
+ }
+
+ // The progress must be 100% at the end
+ compare(loadProgressArray[loadProgressArray.length - 1], 100)
}
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_loadProgressSignal.qml b/tests/auto/quick/qmltests/data/tst_loadProgressSignal.qml
index 8e2e99b64..7b0bac61b 100644
--- a/tests/auto/quick/qmltests/data/tst_loadProgressSignal.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadProgressSignal.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml b/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml
index 2400a5ed6..fb692c472 100644
--- a/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml
@@ -41,7 +41,7 @@
import QtQuick 2.3
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
Item {
width: 300
diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
index 922925b48..c8abf2bb0 100644
--- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
import QtWebEngine.experimental 1.0
TestWebEngineView {
diff --git a/tests/auto/quick/qmltests/data/tst_navigationHistory.qml b/tests/auto/quick/qmltests/data/tst_navigationHistory.qml
index 3acde3abc..f7875bb78 100644
--- a/tests/auto/quick/qmltests/data/tst_navigationHistory.qml
+++ b/tests/auto/quick/qmltests/data/tst_navigationHistory.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
index 72eb0aac9..7d49cda90 100644
--- a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
+++ b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_properties.qml b/tests/auto/quick/qmltests/data/tst_properties.qml
index 738ef532d..9418252cb 100644
--- a/tests/auto/quick/qmltests/data/tst_properties.qml
+++ b/tests/auto/quick/qmltests/data/tst_properties.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_runJavaScript.qml b/tests/auto/quick/qmltests/data/tst_runJavaScript.qml
index 6cf3a71fb..07e7130c6 100644
--- a/tests/auto/quick/qmltests/data/tst_runJavaScript.qml
+++ b/tests/auto/quick/qmltests/data/tst_runJavaScript.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_titleChanged.qml b/tests/auto/quick/qmltests/data/tst_titleChanged.qml
index adc8564c0..8d9dae0a4 100644
--- a/tests/auto/quick/qmltests/data/tst_titleChanged.qml
+++ b/tests/auto/quick/qmltests/data/tst_titleChanged.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
TestWebEngineView {
id: webEngineView
diff --git a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml
index 1c32c73a9..5fefd0fe5 100644
--- a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml
+++ b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
Item {
id: parentItem
diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml
index a9ed933d9..8a3b8207f 100644
--- a/tests/auto/quick/qmltests/data/tst_userScripts.qml
+++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml
@@ -41,7 +41,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
Item {
WebEngineScript {
diff --git a/tests/auto/quick/qmltests/data/tst_webchannel.qml b/tests/auto/quick/qmltests/data/tst_webchannel.qml
index dce585b67..51e37d50e 100644
--- a/tests/auto/quick/qmltests/data/tst_webchannel.qml
+++ b/tests/auto/quick/qmltests/data/tst_webchannel.qml
@@ -40,7 +40,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.1
+import QtWebEngine 1.2
import QtWebEngine.experimental 1.0
import QtWebChannel 1.0
diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/FilePicker.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/FilePicker.qml
new file mode 100644
index 000000000..5ee231c19
--- /dev/null
+++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/FilePicker.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import "../../TestParams" 1.0
+
+QtObject {
+ property bool selectMultiple: false;
+ property bool selectExisting: false;
+ property bool selectFolder: false;
+
+ signal filesSelected(var fileList);
+ signal rejected();
+
+ function open() {
+ FilePickerParams.filePickerOpened = true;
+ if (FilePickerParams.selectFiles)
+ filesSelected(FilePickerParams.selectedFilesUrl)
+ else
+ rejected()
+ }
+}
diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/qmldir b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/qmldir
index 1ebabd335..cf8ac0512 100644
--- a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/qmldir
+++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/UIDelegates/qmldir
@@ -1,4 +1,5 @@
module QtWebEngine.UIDelegates
AlertDialog 1.0 AlertDialog.qml
ConfirmDialog 1.0 ConfirmDialog.qml
+FilePicker 1.0 FilePicker.qml
PromptDialog 1.0 PromptDialog.qml
diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml b/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml
new file mode 100644
index 000000000..f0f2d9368
--- /dev/null
+++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/FilePickerParams.qml
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.0
+
+QtObject {
+ property var selectedFilesUrl: [];
+ property bool selectFiles: false;
+ property bool filePickerOpened: false;
+}
diff --git a/tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir b/tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir
index f2ed87a75..a21dd8236 100644
--- a/tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir
+++ b/tests/auto/quick/qmltests/mock-delegates/TestParams/qmldir
@@ -1,4 +1,5 @@
# QML module so that the autotests can set testing parameters
module TestParams
+singleton FilePickerParams 1.0 FilePickerParams.qml
singleton JSDialogParams 1.0 JSDialogParams.qml
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index 9f6f55275..57649384d 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -12,23 +12,31 @@ OTHER_FILES += \
$$PWD/data/change-document-title.js \
$$PWD/data/download.zip \
$$PWD/data/confirm.html \
+ $$PWD/data/confirmclose.html \
+ $$PWD/data/directoryupload.html \
$$PWD/data/favicon.html \
$$PWD/data/favicon.png \
$$PWD/data/favicon2.html \
+ $$PWD/data/forms.html \
$$PWD/data/geolocation.html \
$$PWD/data/javascript.html \
$$PWD/data/link.html \
$$PWD/data/prompt.html \
+ $$PWD/data/multifileupload.html \
$$PWD/data/redirect.html \
+ $$PWD/data/singlefileupload.html \
$$PWD/data/small-favicon.png \
$$PWD/data/test1.html \
$$PWD/data/test2.html \
$$PWD/data/test3.html \
$$PWD/data/test4.html \
$$PWD/data/keyboardModifierMapping.html \
+ $$PWD/data/titleupdate.js \
$$PWD/data/tst_desktopBehaviorLoadHtml.qml \
$$PWD/data/tst_download.qml \
$$PWD/data/tst_favIconLoad.qml \
+ $$PWD/data/tst_filePicker.qml \
+ $$PWD/data/tst_formValidation.qml \
$$PWD/data/tst_geopermission.qml \
$$PWD/data/tst_javaScriptDialogs.qml \
$$PWD/data/tst_linkHovered.qml \
@@ -49,12 +57,13 @@ OTHER_FILES += \
$$PWD/data/tst_keyboardModifierMapping.qml \
$$PWD/mock-delegates/QtWebEngine/UIDelegates/AlertDialog.qml \
$$PWD/mock-delegates/QtWebEngine/UIDelegates/ConfirmDialog.qml \
+ $$PWD/mock-delegates/QtWebEngine/UIDelegates/FilePicker.qml \
$$PWD/mock-delegates/QtWebEngine/UIDelegates/PromptDialog.qml \
$$PWD/mock-delegates/QtWebEngine/UIDelegates/qmldir \
+ $$PWD/mock-delegates/TestParams/FilePickerParams.qml \
$$PWD/mock-delegates/TestParams/JSDialogParams.qml \
$$PWD/mock-delegates/TestParams/qmldir \
-
load(qt_build_paths)
DEFINES += QUICK_TEST_SOURCE_DIR=\\\"$$re_escape($$PWD$${QMAKE_DIR_SEP}data)\\\"
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index 2cbcf0979..40dc3cb61 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -73,7 +73,7 @@ tst_QQuickWebEngineView::tst_QQuickWebEngineView()
static QQmlEngine *engine = new QQmlEngine(this);
m_component.reset(new QQmlComponent(engine, this));
m_component->setData(QByteArrayLiteral("import QtQuick 2.0\n"
- "import QtWebEngine 1.1\n"
+ "import QtWebEngine 1.2\n"
"WebEngineView {}")
, QUrl());
}
@@ -335,12 +335,10 @@ void tst_QQuickWebEngineView::titleUpdate()
webEngineView()->setUrl(QUrl::fromLocalFile(QLatin1String(TESTS_SOURCE_DIR "html/file_that_does_not_exist.html")));
QVERIFY(waitForLoadFailed(webEngineView()));
QCOMPARE(titleSpy.size(), 0);
-
}
void tst_QQuickWebEngineView::transparentWebEngineViews()
{
-
showWebEngineView();
// This should not crash.
@@ -348,13 +346,10 @@ void tst_QQuickWebEngineView::transparentWebEngineViews()
webEngineView1->setParentItem(m_window->contentItem());
QScopedPointer<QQuickWebEngineView> webEngineView2(newWebEngineView());
webEngineView2->setParentItem(m_window->contentItem());
-#if !defined(QQUICKWEBENGINEVIEW_EXPERIMENTAL_TRANSPARENTBACKGROUND)
- QWARN("QQUICKWEBENGINEVIEW_EXPERIMENTAL_TRANSPARENTBACKGROUND");
-#else
- QVERIFY(!webEngineView1->experimental()->transparentBackground());
- webEngineView2->experimental()->setTransparentBackground(true);
- QVERIFY(webEngineView2->experimental()->transparentBackground());
-#endif
+
+ QVERIFY(webEngineView1->backgroundColor() != Qt::transparent);
+ webEngineView2->setBackgroundColor(Qt::transparent);
+ QVERIFY(webEngineView2->backgroundColor() == Qt::transparent);
webEngineView1->setSize(QSizeF(300, 400));
webEngineView1->loadHtml("<html><body bgcolor=\"red\"></body></html>");
@@ -367,7 +362,24 @@ void tst_QQuickWebEngineView::transparentWebEngineViews()
webEngineView2->setVisible(true);
QTest::qWait(200);
- // FIXME: test actual rendering results; https://bugs.webkit.org/show_bug.cgi?id=80609.
+
+ // Result image: black text on red background.
+ QImage grabbedWindow = m_window->grabWindow();
+
+ QSet<int> redComponents;
+ for (int i = 0, width = grabbedWindow.width(); i < width; i++) {
+ for (int j = 0, height = grabbedWindow.height(); j < height; j++) {
+ QColor color(grabbedWindow.pixel(i, j));
+ redComponents.insert(color.red());
+ // There are no green or blue components between red and black.
+ QVERIFY(color.green() == 0);
+ QVERIFY(color.blue() == 0);
+ }
+ }
+
+ QVERIFY(redComponents.count() > 1);
+ QVERIFY(redComponents.contains(0)); // black
+ QVERIFY(redComponents.contains(255)); // red
}
void tst_QQuickWebEngineView::inputMethod()
diff --git a/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp b/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp
index 5d15537b3..e0e876fc8 100644
--- a/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp
+++ b/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp
@@ -184,7 +184,7 @@ void tst_QQuickWebEngineViewGraphics::reparentToOtherWindow()
void tst_QQuickWebEngineViewGraphics::setHtml(const QString &html)
{
QString htmlData = QUrl::toPercentEncoding(html);
- QString qmlData = QUrl::toPercentEncoding(QStringLiteral("import QtQuick 2.0; import QtWebEngine 1.1; WebEngineView { width: 150; height: 150; url: loadUrl }"));
+ QString qmlData = QUrl::toPercentEncoding(QStringLiteral("import QtQuick 2.0; import QtWebEngine 1.2; WebEngineView { width: 150; height: 150; url: loadUrl }"));
m_view->rootContext()->setContextProperty("loadUrl", QUrl(QStringLiteral("data:text/html,%1").arg(htmlData)));
m_view->setSource(QUrl(QStringLiteral("data:text/plain,%1").arg(qmlData)));
m_view->create();
diff --git a/tests/auto/widgets/qwebengineaccessibility/qwebengineaccessibility.pro b/tests/auto/widgets/qwebengineaccessibility/qwebengineaccessibility.pro
index ff6c49628..e99c7f493 100644
--- a/tests/auto/widgets/qwebengineaccessibility/qwebengineaccessibility.pro
+++ b/tests/auto/widgets/qwebengineaccessibility/qwebengineaccessibility.pro
@@ -1,2 +1 @@
include(../tests.pri)
-exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
diff --git a/tests/auto/widgets/qwebengineframe/qwebengineframe.pro b/tests/auto/widgets/qwebengineframe/qwebengineframe.pro
deleted file mode 100644
index ff6c49628..000000000
--- a/tests/auto/widgets/qwebengineframe/qwebengineframe.pro
+++ /dev/null
@@ -1,2 +0,0 @@
-include(../tests.pri)
-exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
diff --git a/tests/auto/widgets/qwebengineframe/tst_qwebengineframe.cpp b/tests/auto/widgets/qwebengineframe/tst_qwebengineframe.cpp
deleted file mode 100644
index 00e1b1123..000000000
--- a/tests/auto/widgets/qwebengineframe/tst_qwebengineframe.cpp
+++ /dev/null
@@ -1,1654 +0,0 @@
-/*
- Copyright (C) 2008,2009 Nokia Corporation and/or its subsidiary(-ies)
-
- 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 <QtTest/QtTest>
-
-#include <qwebenginepage.h>
-#include <qwebengineview.h>
-#include <qwebenginehistory.h>
-#include <QAbstractItemView>
-#include <QApplication>
-#include <QComboBox>
-#include <QPaintEngine>
-#include <QPicture>
-#include <QRegExp>
-#include <QNetworkRequest>
-#include <QNetworkReply>
-#include <QTextCodec>
-#include <QWebEngineSettings>
-#ifndef QT_NO_OPENSSL
-#include <qsslerror.h>
-#endif
-#include "../util.h"
-
-class tst_QWebEngineFrame : public QObject
-{
- Q_OBJECT
-
-public:
- bool eventFilter(QObject* watched, QEvent* event);
-
-public Q_SLOTS:
- void initTestCase();
- void init();
- void cleanup();
-
-private Q_SLOTS:
- void horizontalScrollAfterBack();
- void symmetricUrl();
- void progressSignal();
- void urlChange();
- void requestedUrl();
- void requestedUrlAfterSetAndLoadFailures();
- void javaScriptWindowObjectCleared_data();
- void javaScriptWindowObjectCleared();
- void javaScriptWindowObjectClearedOnEvaluate();
- void asyncAndDelete();
- void earlyToHtml();
- void setHtml();
- void setHtmlWithImageResource();
- void setHtmlWithStylesheetResource();
- void setHtmlWithBaseURL();
- void setHtmlWithJSAlert();
- void ipv6HostEncoding();
- void metaData();
-#if !defined(QT_NO_COMBOBOX)
- void popupFocus();
-#endif
- void inputFieldFocus();
- void hitTestContent();
- void baseUrl_data();
- void baseUrl();
- void hasSetFocus();
- void renderGeometry();
- void renderHints();
- void scrollPosition();
- void scrollToAnchor();
- void scrollbarsOff();
- void evaluateWillCauseRepaint();
- void setContent_data();
- void setContent();
- void setCacheLoadControlAttribute();
- void setUrlWithPendingLoads();
- void setUrlToEmpty();
- void setUrlToInvalid();
- void setUrlHistory();
- void setUrlUsingStateObject();
- void setUrlSameUrl();
- void setUrlThenLoads_data();
- void setUrlThenLoads();
- void loadFinishedAfterNotFoundError();
- void loadInSignalHandlers_data();
- void loadInSignalHandlers();
-
-private:
- QWebEngineView* m_view;
- QWebEnginePage* m_page;
- QWebEngineView* m_inputFieldsTestView;
- int m_inputFieldTestPaintCount;
-};
-
-bool tst_QWebEngineFrame::eventFilter(QObject* watched, QEvent* event)
-{
- // used on the inputFieldFocus test
- if (watched == m_inputFieldsTestView) {
- if (event->type() == QEvent::Paint)
- m_inputFieldTestPaintCount++;
- }
- return QObject::eventFilter(watched, event);
-}
-
-void tst_QWebEngineFrame::initTestCase()
-{
-}
-
-void tst_QWebEngineFrame::init()
-{
- m_view = new QWebEngineView();
- m_page = m_view->page();
- m_page->settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
-}
-
-void tst_QWebEngineFrame::cleanup()
-{
- delete m_view;
-}
-
-void tst_QWebEngineFrame::symmetricUrl()
-{
- QWebEngineView view;
- QSignalSpy loadFinishedSpy(view.page(), SIGNAL(loadFinished(bool)));
-
- QVERIFY(view.url().isEmpty());
-
- QCOMPARE(view.history()->count(), 0);
-
- QUrl dataUrl("data:text/html,<h1>Test");
-
- view.setUrl(dataUrl);
- QCOMPARE(view.url(), dataUrl);
- QCOMPARE(view.history()->count(), 0);
-
- // loading is _not_ immediate, so the text isn't set just yet.
- QVERIFY(toPlainTextSync(view.page()).isEmpty());
-
- QTRY_COMPARE(loadFinishedSpy.count(), 1);
-
- QCOMPARE(view.history()->count(), 1);
- QCOMPARE(toPlainTextSync(view.page()), QString("Test"));
-
- QUrl dataUrl2("data:text/html,<h1>Test2");
- QUrl dataUrl3("data:text/html,<h1>Test3");
-
- view.setUrl(dataUrl2);
- view.setUrl(dataUrl3);
-
- QCOMPARE(view.url(), dataUrl3);
-
- QTRY_VERIFY(loadFinishedSpy.count() >= 2);
- QTRY_COMPARE(loadFinishedSpy.count(), 3);
-
- QCOMPARE(view.history()->count(), 2);
-
- QCOMPARE(toPlainTextSync(view.page()), QString("Test3"));
-}
-
-void tst_QWebEngineFrame::progressSignal()
-{
- QSignalSpy progressSpy(m_view, SIGNAL(loadProgress(int)));
-
- QUrl dataUrl("data:text/html,<h1>Test");
- m_view->setUrl(dataUrl);
-
- ::waitForSignal(m_view, SIGNAL(loadFinished(bool)));
-
- QVERIFY(progressSpy.size() >= 2);
- int previousValue = -1;
- for (QSignalSpy::ConstIterator it = progressSpy.begin(); it < progressSpy.end(); ++it) {
- int current = (*it).first().toInt();
- QVERIFY(current > previousValue);
- previousValue = current;
- }
-
- // But we always end at 100%
- QCOMPARE(progressSpy.last().first().toInt(), 100);
-}
-
-void tst_QWebEngineFrame::urlChange()
-{
- QSignalSpy urlSpy(m_page, SIGNAL(urlChanged(QUrl)));
-
- QUrl dataUrl("data:text/html,<h1>Test");
- m_view->setUrl(dataUrl);
-
- ::waitForSignal(m_page, SIGNAL(urlChanged(QUrl)));
-
- QCOMPARE(urlSpy.size(), 1);
-
- QUrl dataUrl2("data:text/html,<html><head><title>title</title></head><body><h1>Test</body></html>");
- m_view->setUrl(dataUrl2);
-
- ::waitForSignal(m_page, SIGNAL(urlChanged(QUrl)));
-
- QCOMPARE(urlSpy.size(), 2);
-}
-
-class FakeReply : public QNetworkReply {
- Q_OBJECT
-
-public:
- static const QUrl urlFor404ErrorWithoutContents;
-
- FakeReply(const QNetworkRequest& request, QObject* parent = 0)
- : QNetworkReply(parent)
- {
- setOperation(QNetworkAccessManager::GetOperation);
- setRequest(request);
- setUrl(request.url());
- if (request.url() == QUrl("qrc:/test1.html")) {
- setHeader(QNetworkRequest::LocationHeader, QString("qrc:/test2.html"));
- setAttribute(QNetworkRequest::RedirectionTargetAttribute, QUrl("qrc:/test2.html"));
- QTimer::singleShot(0, this, SLOT(continueRedirect()));
- }
-#ifndef QT_NO_OPENSSL
- else if (request.url() == QUrl("qrc:/fake-ssl-error.html")) {
- setError(QNetworkReply::SslHandshakeFailedError, tr("Fake error!"));
- QTimer::singleShot(0, this, SLOT(continueError()));
- }
-#endif
- else if (request.url().host() == QLatin1String("abcdef.abcdef")) {
- setError(QNetworkReply::HostNotFoundError, tr("Invalid URL"));
- QTimer::singleShot(0, this, SLOT(continueError()));
- } else if (request.url() == FakeReply::urlFor404ErrorWithoutContents) {
- setError(QNetworkReply::ContentNotFoundError, "Not found");
- setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 404);
- QTimer::singleShot(0, this, SLOT(continueError()));
- }
-
- open(QIODevice::ReadOnly);
- }
- ~FakeReply()
- {
- close();
- }
- virtual void abort() {}
- virtual void close() {}
-
-protected:
- qint64 readData(char*, qint64)
- {
- return 0;
- }
-
-private Q_SLOTS:
- void continueRedirect()
- {
- emit metaDataChanged();
- emit finished();
- }
-
- void continueError()
- {
- emit error(this->error());
- emit finished();
- }
-};
-
-const QUrl FakeReply::urlFor404ErrorWithoutContents = QUrl("http://this.will/return-http-404-error-without-contents.html");
-
-class FakeNetworkManager : public QNetworkAccessManager {
- Q_OBJECT
-
-public:
- FakeNetworkManager(QObject* parent) : QNetworkAccessManager(parent) { }
-
-protected:
- virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
- {
- QString url = request.url().toString();
- if (op == QNetworkAccessManager::GetOperation) {
-#ifndef QT_NO_OPENSSL
- if (url == "qrc:/fake-ssl-error.html") {
- FakeReply* reply = new FakeReply(request, this);
- QList<QSslError> errors;
- emit sslErrors(reply, errors << QSslError(QSslError::UnspecifiedError));
- return reply;
- }
-#endif
- if (url == "qrc:/test1.html" || url == "http://abcdef.abcdef/" || request.url() == FakeReply::urlFor404ErrorWithoutContents)
- return new FakeReply(request, this);
- }
-
- return QNetworkAccessManager::createRequest(op, request, outgoingData);
- }
-};
-
-void tst_QWebEngineFrame::requestedUrl()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- QWebEnginePage page;
-
- // in few seconds, the image should be completely loaded
- QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
- FakeNetworkManager* networkManager = new FakeNetworkManager(&page);
- page.setNetworkAccessManager(networkManager);
-
- page.setUrl(QUrl("qrc:/test1.html"));
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(spy.count(), 1);
- QCOMPARE(page.requestedUrl(), QUrl("qrc:/test1.html"));
- QCOMPARE(page.url(), QUrl("qrc:/test2.html"));
-
- page.setUrl(QUrl("qrc:/non-existent.html"));
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(spy.count(), 2);
- QCOMPARE(page.requestedUrl(), QUrl("qrc:/non-existent.html"));
- QCOMPARE(page.url(), QUrl("qrc:/non-existent.html"));
-
- page.setUrl(QUrl("http://abcdef.abcdef"));
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(spy.count(), 3);
- QCOMPARE(page.requestedUrl(), QUrl("http://abcdef.abcdef/"));
- QCOMPARE(page.url(), QUrl("http://abcdef.abcdef/"));
-
-#ifndef QT_NO_OPENSSL
- qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
- qRegisterMetaType<QNetworkReply* >("QNetworkReply*");
-
- QSignalSpy spy2(page.networkAccessManager(), SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)));
- page.setUrl(QUrl("qrc:/fake-ssl-error.html"));
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(spy2.count(), 1);
- QCOMPARE(page.requestedUrl(), QUrl("qrc:/fake-ssl-error.html"));
- QCOMPARE(page.url(), QUrl("qrc:/fake-ssl-error.html"));
-#endif
-#endif
-}
-
-void tst_QWebEngineFrame::requestedUrlAfterSetAndLoadFailures()
-{
- QWebEnginePage page;
- page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
- QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
-
- const QUrl first("http://abcdef.abcdef/");
- page.setUrl(first);
- ::waitForSignal(&page, SIGNAL(loadFinished(bool)));
- QCOMPARE(spy.count(), 1);
- QCOMPARE(page.url(), first);
- QCOMPARE(page.requestedUrl(), first);
- QVERIFY(!spy.at(0).first().toBool());
-
- const QUrl second("http://abcdef.abcdef/another_page.html");
- QVERIFY(first != second);
-
- page.load(second);
- ::waitForSignal(&page, SIGNAL(loadFinished(bool)));
- QCOMPARE(spy.count(), 2);
- QCOMPARE(page.url(), first);
- QCOMPARE(page.requestedUrl(), second);
- QVERIFY(!spy.at(1).first().toBool());
-}
-
-void tst_QWebEngineFrame::javaScriptWindowObjectCleared_data()
-{
- QTest::addColumn<QString>("html");
- QTest::addColumn<int>("signalCount");
- QTest::newRow("with <script>") << "<html><body><script>i=0</script><p>hello world</p></body></html>" << 1;
- // NOTE: Empty scripts no longer cause this signal to be emitted.
- QTest::newRow("with empty <script>") << "<html><body><script></script><p>hello world</p></body></html>" << 0;
- QTest::newRow("without <script>") << "<html><body><p>hello world</p></body></html>" << 0;
-}
-
-void tst_QWebEngineFrame::javaScriptWindowObjectCleared()
-{
-#if !defined(QWEBENGINEPAGE_JAVASCRIPTWINDOWOBJECTCLEARED)
- QSKIP("QWEBENGINEPAGE_JAVASCRIPTWINDOWOBJECTCLEARED");
-#else
- QWebEnginePage page;
- QSignalSpy spy(&page, SIGNAL(javaScriptWindowObjectCleared()));
- QFETCH(QString, html);
- page.setHtml(html);
-
- QFETCH(int, signalCount);
- QCOMPARE(spy.count(), signalCount);
-#endif
-}
-
-void tst_QWebEngineFrame::javaScriptWindowObjectClearedOnEvaluate()
-{
-#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
- QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
-#else
- QWebEnginePage page;
- QSignalSpy spy(&page, SIGNAL(javaScriptWindowObjectCleared()));
- page.setHtml("<html></html>");
- QCOMPARE(spy.count(), 0);
- page.evaluateJavaScript("var a = 'a';");
- QCOMPARE(spy.count(), 1);
- // no new clear for a new script:
- page.evaluateJavaScript("var a = 1;");
- QCOMPARE(spy.count(), 1);
-#endif
-}
-
-void tst_QWebEngineFrame::asyncAndDelete()
-{
- QWebEnginePage *page = new QWebEnginePage;
- CallbackSpy<QString> plainTextSpy;
- CallbackSpy<QString> htmlSpy;
- page->toPlainText(plainTextSpy.ref());
- page->toHtml(htmlSpy.ref());
-
- delete page;
- // Pending callbacks should be called with an empty value in the page's destructor.
- QCOMPARE(plainTextSpy.waitForResult(), QString());
- QVERIFY(plainTextSpy.wasCalled());
- QCOMPARE(htmlSpy.waitForResult(), QString());
- QVERIFY(htmlSpy.wasCalled());
-}
-
-void tst_QWebEngineFrame::earlyToHtml()
-{
- QString html("<html><head></head><body></body></html>");
- QCOMPARE(toHtmlSync(m_view->page()), html);
-}
-
-void tst_QWebEngineFrame::setHtml()
-{
- QString html("<html><head></head><body><p>hello world</p></body></html>");
- QSignalSpy spy(m_view->page(), SIGNAL(loadFinished(bool)));
- m_view->page()->setHtml(html);
- QVERIFY(spy.wait());
- QCOMPARE(toHtmlSync(m_view->page()), html);
-}
-
-void tst_QWebEngineFrame::setHtmlWithImageResource()
-{
- // By default, only security origins of local files can load local resources.
- // So we should specify baseUrl to be a local file in order to get a proper origin and load the local image.
-
- QLatin1String html("<html><body><p>hello world</p><img src='qrc:/image.png'/></body></html>");
- QWebEnginePage page;
-
- page.setHtml(html, QUrl(QLatin1String("file:///path/to/file")));
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
-
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images.length").toInt(), 1);
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 128);
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 128);
-
- // Now we test the opposite: without a baseUrl as a local file, we cannot request local resources.
-
- page.setHtml(html);
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images.length").toInt(), 1);
- QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118659", Continue);
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 0);
- QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118659", Continue);
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 0);
-}
-
-void tst_QWebEngineFrame::setHtmlWithStylesheetResource()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- // By default, only security origins of local files can load local resources.
- // So we should specify baseUrl to be a local file in order to be able to download the local stylesheet.
-
- const char* htmlData =
- "<html>"
- "<head>"
- "<link rel='stylesheet' href='qrc:/style.css' type='text/css' />"
- "</head>"
- "<body>"
- "<p id='idP'>some text</p>"
- "</body>"
- "</html>";
- QLatin1String html(htmlData);
- QWebEnginePage page;
- QWebEngineElement webElement;
-
- page.setHtml(html, QUrl(QLatin1String("qrc:///file")));
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
- webElement = page.documentElement().findFirst("p");
- QCOMPARE(webElement.styleProperty("color", QWebEngineElement::CascadedStyle), QLatin1String("red"));
-
- // Now we test the opposite: without a baseUrl as a local file, we cannot request local resources.
-
- page.setHtml(html, QUrl(QLatin1String("http://www.example.com/")));
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
- webElement = page.documentElement().findFirst("p");
- QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118659", Continue);
- QCOMPARE(webElement.styleProperty("color", QWebEngineElement::CascadedStyle), QString());
-#endif
-}
-
-void tst_QWebEngineFrame::setHtmlWithBaseURL()
-{
- // This tests if baseUrl is indeed affecting the relative paths from resources.
- // As we are using a local file as baseUrl, its security origin should be able to load local resources.
-
- if (!QDir(TESTS_SOURCE_DIR).exists())
- W_QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll);
-
- QDir::setCurrent(TESTS_SOURCE_DIR);
-
- QString html("<html><body><p>hello world</p><img src='resources/image2.png'/></body></html>");
-
- QWebEnginePage page;
-
- // in few seconds, the image should be completey loaded
- QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
-
- page.setHtml(html, QUrl::fromLocalFile(TESTS_SOURCE_DIR));
- waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(spy.count(), 1);
-
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images.length").toInt(), 1);
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 128);
- QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 128);
-
- // no history item has to be added.
- QCOMPARE(m_view->page()->history()->count(), 0);
-}
-
-class MyPage : public QWebEnginePage
-{
-public:
- MyPage() : QWebEnginePage(), alerts(0) {}
- int alerts;
-
-protected:
- virtual void javaScriptAlert(const QUrl &securityOrigin, const QString &msg)
- {
- alerts++;
- QCOMPARE(securityOrigin, QUrl(QStringLiteral("http://test.origin.com/")));
- QCOMPARE(msg, QString("foo"));
- }
-};
-
-void tst_QWebEngineFrame::setHtmlWithJSAlert()
-{
- QString html("<html><head></head><body><script>alert('foo');</script><p>hello world</p></body></html>");
- MyPage page;
- page.setHtml(html, QUrl(QStringLiteral("http://test.origin.com/path#fragment")));
- waitForSignal(&page, SIGNAL(loadFinished(bool)));
- QCOMPARE(page.alerts, 1);
- QCOMPARE(toHtmlSync(&page), html);
-}
-
-class TestNetworkManager : public QNetworkAccessManager
-{
-public:
- TestNetworkManager(QObject* parent) : QNetworkAccessManager(parent) {}
-
- QList<QUrl> requestedUrls;
-
-protected:
- virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest &request, QIODevice* outgoingData) {
- requestedUrls.append(request.url());
- QNetworkRequest redirectedRequest = request;
- redirectedRequest.setUrl(QUrl("data:text/html,<p>hello"));
- return QNetworkAccessManager::createRequest(op, redirectedRequest, outgoingData);
- }
-};
-
-void tst_QWebEngineFrame::ipv6HostEncoding()
-{
-#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
- QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
-#else
- TestNetworkManager* networkManager = new TestNetworkManager(m_page);
- m_page->setNetworkAccessManager(networkManager);
- networkManager->requestedUrls.clear();
-
- QUrl baseUrl = QUrl::fromEncoded("http://[::1]/index.html");
- m_view->setHtml("<p>Hi", baseUrl);
- m_view->page()->evaluateJavaScript("var r = new XMLHttpRequest();"
- "r.open('GET', 'http://[::1]/test.xml', false);"
- "r.send(null);"
- );
- QCOMPARE(networkManager->requestedUrls.count(), 1);
- QCOMPARE(networkManager->requestedUrls.at(0), QUrl::fromEncoded("http://[::1]/test.xml"));
-#endif
-}
-
-void tst_QWebEngineFrame::metaData()
-{
-#if !defined(QWEBENGINEPAGE_METADATA)
- QSKIP("QWEBENGINEPAGE_METADATA");
-#else
- m_view->setHtml("<html>"
- " <head>"
- " <meta name=\"description\" content=\"Test description\">"
- " <meta name=\"keywords\" content=\"HTML, JavaScript, Css\">"
- " </head>"
- "</html>");
-
- QMultiMap<QString, QString> metaData = m_view->page()->metaData();
-
- QCOMPARE(metaData.count(), 2);
-
- QCOMPARE(metaData.value("description"), QString("Test description"));
- QCOMPARE(metaData.value("keywords"), QString("HTML, JavaScript, Css"));
- QCOMPARE(metaData.value("nonexistent"), QString());
-
- m_view->setHtml("<html>"
- " <head>"
- " <meta name=\"samekey\" content=\"FirstValue\">"
- " <meta name=\"samekey\" content=\"SecondValue\">"
- " </head>"
- "</html>");
-
- metaData = m_view->page()->metaData();
-
- QCOMPARE(metaData.count(), 2);
-
- QStringList values = metaData.values("samekey");
- QCOMPARE(values.count(), 2);
-
- QVERIFY(values.contains("FirstValue"));
- QVERIFY(values.contains("SecondValue"));
-
- QCOMPARE(metaData.value("nonexistent"), QString());
-#endif
-}
-
-#if !defined(QT_NO_COMBOBOX)
-void tst_QWebEngineFrame::popupFocus()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- QWebEngineView view;
- view.setHtml("<html>"
- " <body>"
- " <select name=\"select\">"
- " <option>1</option>"
- " <option>2</option>"
- " </select>"
- " <input type=\"text\"> </input>"
- " <textarea name=\"text_area\" rows=\"3\" cols=\"40\">"
- "This test checks whether showing and hiding a popup"
- "takes the focus away from the webpage."
- " </textarea>"
- " </body>"
- "</html>");
- view.resize(400, 100);
- // Call setFocus before show to work around http://bugreports.qt.nokia.com/browse/QTBUG-14762
- view.setFocus();
- view.show();
- QTest::qWaitForWindowExposed(&view);
- view.activateWindow();
- QTRY_VERIFY(view.hasFocus());
-
- // open the popup by clicking. check if focus is on the popup
- const QWebEngineElement webCombo = view.page()->documentElement().findFirst(QLatin1String("select[name=select]"));
- QTest::mouseClick(&view, Qt::LeftButton, 0, webCombo.geometry().center());
-
- QComboBox* combo = view.findChild<QComboBox*>();
- QVERIFY(combo != 0);
- QTRY_VERIFY(!view.hasFocus() && combo->view()->hasFocus()); // Focus should be on the popup
-
- // hide the popup and check if focus is on the page
- combo->hidePopup();
- QTRY_VERIFY(view.hasFocus()); // Focus should be back on the WebView
-#endif
-}
-#endif
-
-void tst_QWebEngineFrame::inputFieldFocus()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- QWebEngineView view;
- view.setHtml("<html><body><input type=\"text\"></input></body></html>");
- view.resize(400, 100);
- view.show();
- QTest::qWaitForWindowExposed(&view);
- view.activateWindow();
- view.setFocus();
- QTRY_VERIFY(view.hasFocus());
-
- // double the flashing time, should at least blink once already
- int delay = qApp->cursorFlashTime() * 2;
-
- // focus the lineedit and check if it blinks
- bool autoSipEnabled = qApp->autoSipEnabled();
- qApp->setAutoSipEnabled(false);
- const QWebEngineElement inputElement = view.page()->documentElement().findFirst(QLatin1String("input[type=text]"));
- QTest::mouseClick(&view, Qt::LeftButton, 0, inputElement.geometry().center());
- m_inputFieldsTestView = &view;
- view.installEventFilter( this );
- QTest::qWait(delay);
- QVERIFY2(m_inputFieldTestPaintCount >= 3,
- "The input field should have a blinking caret");
- qApp->setAutoSipEnabled(autoSipEnabled);
-#endif
-}
-
-void tst_QWebEngineFrame::hitTestContent()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- QString html("<html><body><p>A paragraph</p><br/><br/><br/><a href=\"about:blank\" target=\"_foo\" id=\"link\">link text</a></body></html>");
-
- QWebEnginePage page;
- page.setHtml(html);
- page.setViewportSize(QSize(200, 0)); //no height so link is not visible
- const QWebEngineElement linkElement = page.documentElement().findFirst(QLatin1String("a#link"));
- QWebEngineHitTestResult result = page.hitTestContent(linkElement.geometry().center());
- QCOMPARE(result.linkText(), QString("link text"));
- QWebEngineElement link = result.linkElement();
- QCOMPARE(link.attribute("target"), QString("_foo"));
-#endif
-}
-
-void tst_QWebEngineFrame::baseUrl_data()
-{
- QTest::addColumn<QString>("html");
- QTest::addColumn<QUrl>("loadUrl");
- QTest::addColumn<QUrl>("url");
- QTest::addColumn<QUrl>("baseUrl");
-
- QTest::newRow("null") << QString() << QUrl()
- << QUrl("about:blank") << QUrl("about:blank");
-
- QTest::newRow("foo") << QString() << QUrl("http://foobar.baz/")
- << QUrl("http://foobar.baz/") << QUrl("http://foobar.baz/");
-
- QString html = "<html>"
- "<head>"
- "<base href=\"http://foobaz.bar/\" />"
- "</head>"
- "</html>";
- QTest::newRow("customBaseUrl") << html << QUrl("http://foobar.baz/")
- << QUrl("http://foobar.baz/") << QUrl("http://foobaz.bar/");
-}
-
-void tst_QWebEngineFrame::baseUrl()
-{
- QFETCH(QString, html);
- QFETCH(QUrl, loadUrl);
- QFETCH(QUrl, url);
- QFETCH(QUrl, baseUrl);
-
- QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool)));
- m_page->setHtml(html, loadUrl);
- QTRY_COMPARE(loadSpy.count(), 1);
- QCOMPARE(m_page->url(), url);
- QEXPECT_FAIL("null", "Slight change: We now translate QUrl() to about:blank for the virtual url, but not for the baseUrl", Continue);
- QCOMPARE(baseUrlSync(m_page), baseUrl);
-}
-
-void tst_QWebEngineFrame::hasSetFocus()
-{
-#if !defined(QWEBENGINEFRAME)
- QSKIP("QWEBENGINEFRAME");
-#else
- QString html("<html><body><p>top</p>" \
- "<iframe width='80%' height='30%'/>" \
- "</body></html>");
-
- QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool)));
- m_page->setHtml(html);
-
- waitForSignal(m_page, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(loadSpy.size(), 1);
-
- QList<QWebEngineFrame*> children = m_page->childFrames();
- QWebEngineFrame* frame = children.at(0);
- QString innerHtml("<html><body><p>another iframe</p>" \
- "<iframe width='80%' height='30%'/>" \
- "</body></html>");
- frame->setHtml(innerHtml);
-
- waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(loadSpy.size(), 2);
-
- m_page->setFocus();
- QTRY_VERIFY(m_page->hasFocus());
-
- for (int i = 0; i < children.size(); ++i) {
- children.at(i)->setFocus();
- QTRY_VERIFY(children.at(i)->hasFocus());
- QVERIFY(!m_page->hasFocus());
- }
-
- m_page->setFocus();
- QTRY_VERIFY(m_page->hasFocus());
-#endif
-}
-
-void tst_QWebEngineFrame::renderGeometry()
-{
-#if !defined(QWEBENGINEFRAME)
- QSKIP("QWEBENGINEFRAME");
-#else
- QString html("<html>" \
- "<head><style>" \
- "body, iframe { margin: 0px; border: none; }" \
- "</style></head>" \
- "<body><iframe width='100px' height='100px'/></body>" \
- "</html>");
-
- QWebEnginePage page;
- page.setHtml(html);
-
- QList<QWebEngineFrame*> frames = page.childFrames();
- QWebEngineFrame *frame = frames.at(0);
- QString innerHtml("<body style='margin: 0px;'><img src='qrc:/image.png'/></body>");
-
- // By default, only security origins of local files can load local resources.
- // So we should specify baseUrl to be a local file in order to get a proper origin.
- frame->setHtml(innerHtml, QUrl("file:///path/to/file"));
- waitForSignal(frame, SIGNAL(loadFinished(bool)), 200);
-
- QPicture picture;
-
- QSize size = page.contentsSize();
- page.setViewportSize(size);
-
- // render contents layer only (the iframe is smaller than the image, so it will have scrollbars)
- QPainter painter1(&picture);
- frame->render(&painter1, QWebEngineFrame::ContentsLayer);
- painter1.end();
-
- QCOMPARE(size.width(), picture.boundingRect().width() + frame->scrollBarGeometry(Qt::Vertical).width());
- QCOMPARE(size.height(), picture.boundingRect().height() + frame->scrollBarGeometry(Qt::Horizontal).height());
-
- // render everything, should be the size of the iframe
- QPainter painter2(&picture);
- frame->render(&painter2, QWebEngineFrame::AllLayers);
- painter2.end();
-
- QCOMPARE(size.width(), picture.boundingRect().width()); // width: 100px
- QCOMPARE(size.height(), picture.boundingRect().height()); // height: 100px
-#endif
-}
-
-
-class DummyPaintEngine: public QPaintEngine {
-public:
-
- DummyPaintEngine()
- : QPaintEngine(QPaintEngine::AllFeatures)
- , renderHints(0)
- {
- }
-
- bool begin(QPaintDevice*)
- {
- setActive(true);
- return true;
- }
-
- bool end()
- {
- setActive(false);
- return false;
- }
-
- void updateState(const QPaintEngineState& state)
- {
- renderHints = state.renderHints();
- }
-
- void drawPath(const QPainterPath&) { }
- void drawPixmap(const QRectF&, const QPixmap&, const QRectF&) { }
-
- QPaintEngine::Type type() const
- {
- return static_cast<QPaintEngine::Type>(QPaintEngine::User + 2);
- }
-
- QPainter::RenderHints renderHints;
-};
-
-class DummyPaintDevice: public QPaintDevice {
-public:
- DummyPaintDevice()
- : QPaintDevice()
- , m_engine(new DummyPaintEngine)
- {
- }
-
- ~DummyPaintDevice()
- {
- delete m_engine;
- }
-
- QPaintEngine* paintEngine() const
- {
- return m_engine;
- }
-
- QPainter::RenderHints renderHints() const
- {
- return m_engine->renderHints;
- }
-
-protected:
- int metric(PaintDeviceMetric metric) const;
-
-private:
- DummyPaintEngine* m_engine;
- friend class DummyPaintEngine;
-};
-
-
-int DummyPaintDevice::metric(PaintDeviceMetric metric) const
-{
- switch (metric) {
- case PdmWidth:
- return 400;
- break;
-
- case PdmHeight:
- return 200;
- break;
-
- case PdmNumColors:
- return INT_MAX;
- break;
-
- case PdmDepth:
- return 32;
- break;
-
- default:
- break;
- }
- return 0;
-}
-
-void tst_QWebEngineFrame::renderHints()
-{
-#if !defined(QWEBENGINEPAGE_RENDER)
- QSKIP("QWEBENGINEPAGE_RENDER");
-#else
- QString html("<html><body><p>Hello, world!</p></body></html>");
-
- QWebEnginePage page;
- page.setHtml(html);
- page.setViewportSize(page.contentsSize());
-
- // We will call frame->render and trap the paint engine state changes
- // to ensure that GraphicsContext does not clobber the render hints.
- DummyPaintDevice buffer;
- QPainter painter(&buffer);
-
- painter.setRenderHint(QPainter::TextAntialiasing, false);
- page.render(&painter);
- QVERIFY(!(buffer.renderHints() & QPainter::TextAntialiasing));
- QVERIFY(!(buffer.renderHints() & QPainter::SmoothPixmapTransform));
- QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
-
- painter.setRenderHint(QPainter::TextAntialiasing, true);
- page.render(&painter);
- QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
- QVERIFY(!(buffer.renderHints() & QPainter::SmoothPixmapTransform));
- QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
-
- painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
- page.render(&painter);
- QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
- QVERIFY(buffer.renderHints() & QPainter::SmoothPixmapTransform);
- QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
-
- painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
- page.render(&painter);
- QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
- QVERIFY(buffer.renderHints() & QPainter::SmoothPixmapTransform);
- QVERIFY(buffer.renderHints() & QPainter::HighQualityAntialiasing);
-#endif
-}
-
-void tst_QWebEngineFrame::scrollPosition()
-{
-#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
- QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
-#else
- // enlarged image in a small viewport, to provoke the scrollbars to appear
- QString html("<html><body><img src='qrc:/image.png' height=500 width=500/></body></html>");
-
- QWebEnginePage page;
- page.setViewportSize(QSize(200, 200));
-
- page.setHtml(html);
- page.setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
- page.setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
-
- // try to set the scroll offset programmatically
- page.setScrollPosition(QPoint(23, 29));
- QCOMPARE(page.scrollPosition().x(), 23);
- QCOMPARE(page.scrollPosition().y(), 29);
-
- int x = page.evaluateJavaScript("window.scrollX").toInt();
- int y = page.evaluateJavaScript("window.scrollY").toInt();
- QCOMPARE(x, 23);
- QCOMPARE(y, 29);
-#endif
-}
-
-void tst_QWebEngineFrame::scrollToAnchor()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- QWebEnginePage page;
- page.setViewportSize(QSize(480, 800));
-
- QString html("<html><body><p style=\"margin-bottom: 1500px;\">Hello.</p>"
- "<p><a id=\"foo\">This</a> is an anchor</p>"
- "<p style=\"margin-bottom: 1500px;\"><a id=\"bar\">This</a> is another anchor</p>"
- "</body></html>");
- page.setHtml(html);
- page.setScrollPosition(QPoint(0, 0));
- QCOMPARE(page.scrollPosition().x(), 0);
- QCOMPARE(page.scrollPosition().y(), 0);
-
- QWebEngineElement fooAnchor = page.findFirstElement("a[id=foo]");
-
- page.scrollToAnchor("foo");
- QCOMPARE(page.scrollPosition().y(), fooAnchor.geometry().top());
-
- page.scrollToAnchor("bar");
- page.scrollToAnchor("foo");
- QCOMPARE(page.scrollPosition().y(), fooAnchor.geometry().top());
-
- page.scrollToAnchor("top");
- QCOMPARE(page.scrollPosition().y(), 0);
-
- page.scrollToAnchor("bar");
- page.scrollToAnchor("notexist");
- QVERIFY(page.scrollPosition().y() != 0);
-#endif
-}
-
-
-void tst_QWebEngineFrame::scrollbarsOff()
-{
-#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
- QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
-#else
- QWebEngineView view;
- QWebEngineFrame* mainFrame = view.page();
-
- mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
- mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
-
- QString html("<script>" \
- " function checkScrollbar() {" \
- " if (innerWidth === document.documentElement.offsetWidth)" \
- " document.getElementById('span1').innerText = 'SUCCESS';" \
- " else" \
- " document.getElementById('span1').innerText = 'FAIL';" \
- " }" \
- "</script>" \
- "<body>" \
- " <div style='margin-top:1000px ; margin-left:1000px'>" \
- " <a id='offscreen' href='a'>End</a>" \
- " </div>" \
- "<span id='span1'></span>" \
- "</body>");
-
-
- QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
- view.setHtml(html);
- ::waitForSignal(&view, SIGNAL(loadFinished(bool)), 200);
- QCOMPARE(loadSpy.count(), 1);
-
- mainFrame->evaluateJavaScript("checkScrollbar();");
- QCOMPARE(mainFrame->documentElement().findAll("span").at(0).toPlainText(), QString("SUCCESS"));
-#endif
-}
-
-void tst_QWebEngineFrame::horizontalScrollAfterBack()
-{
-#if !defined(QWEBENGINESETTINGS)
- QSKIP("QWEBENGINESETTINGS");
-#else
- QWebEngineView view;
- QSignalSpy loadSpy(view.page(), SIGNAL(loadFinished(bool)));
-
- view.page()->settings()->setMaximumPagesInCache(2);
- view.page()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAsNeeded);
- view.page()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAsNeeded);
-
- view.load(QUrl("qrc:/testiframe2.html"));
- view.resize(200, 200);
- QTRY_COMPARE(loadSpy.count(), 1);
- QTRY_VERIFY((view.page()->scrollBarGeometry(Qt::Horizontal)).height());
-
- view.load(QUrl("qrc:/testiframe.html"));
- QTRY_COMPARE(loadSpy.count(), 2);
-
- view.page()->triggerAction(QWebEnginePage::Back);
- QTRY_COMPARE(loadSpy.count(), 3);
- QTRY_VERIFY((view.page()->scrollBarGeometry(Qt::Horizontal)).height());
-#endif
-}
-
-void tst_QWebEngineFrame::evaluateWillCauseRepaint()
-{
-#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
- QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
-#else
- QWebEngineView view;
- QString html("<html><body>top<div id=\"junk\" style=\"display: block;\">"
- "junk</div>bottom</body></html>");
- view.setHtml(html);
- view.show();
-
- QTest::qWaitForWindowExposed(&view);
- view.page()->evaluateJavaScript(
- "document.getElementById('junk').style.display = 'none';");
-
- ::waitForSignal(view.page(), SIGNAL(repaintRequested(QRect)));
-#endif
-}
-
-void tst_QWebEngineFrame::setContent_data()
-{
- QTest::addColumn<QString>("mimeType");
- QTest::addColumn<QByteArray>("testContents");
- QTest::addColumn<QString>("expected");
-
- QString str = QString::fromUtf8("ὕαλον ϕαγεῖν δύναμαι· τοῦτο οὔ με βλάπτει");
- QTest::newRow("UTF-8 plain text") << "text/plain; charset=utf-8" << str.toUtf8() << str;
-
- QTextCodec *utf16 = QTextCodec::codecForName("UTF-16");
- if (utf16)
- QTest::newRow("UTF-16 plain text") << "text/plain; charset=utf-16" << utf16->fromUnicode(str) << str;
-
- str = QString::fromUtf8("Une chaîne de caractères à sa façon.");
- QTest::newRow("latin-1 plain text") << "text/plain; charset=iso-8859-1" << str.toLatin1() << str;
-
-
-}
-
-void tst_QWebEngineFrame::setContent()
-{
- QFETCH(QString, mimeType);
- QFETCH(QByteArray, testContents);
- QFETCH(QString, expected);
- QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool)));
- m_view->setContent(testContents, mimeType);
- QVERIFY(loadSpy.wait());
- QCOMPARE(toPlainTextSync(m_view->page()), expected);
-}
-
-class CacheNetworkAccessManager : public QNetworkAccessManager {
-public:
- CacheNetworkAccessManager(QObject* parent = 0)
- : QNetworkAccessManager(parent)
- , m_lastCacheLoad(QNetworkRequest::PreferNetwork)
- {
- }
-
- virtual QNetworkReply* createRequest(Operation, const QNetworkRequest& request, QIODevice*)
- {
- QVariant cacheLoad = request.attribute(QNetworkRequest::CacheLoadControlAttribute);
- if (cacheLoad.isValid())
- m_lastCacheLoad = static_cast<QNetworkRequest::CacheLoadControl>(cacheLoad.toUInt());
- else
- m_lastCacheLoad = QNetworkRequest::PreferNetwork; // default value
- return new FakeReply(request, this);
- }
-
- QNetworkRequest::CacheLoadControl lastCacheLoad() const
- {
- return m_lastCacheLoad;
- }
-
-private:
- QNetworkRequest::CacheLoadControl m_lastCacheLoad;
-};
-
-void tst_QWebEngineFrame::setCacheLoadControlAttribute()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- QWebEnginePage page;
- CacheNetworkAccessManager* manager = new CacheNetworkAccessManager(&page);
- page.setNetworkAccessManager(manager);
-
- QNetworkRequest request(QUrl("http://abcdef.abcdef/"));
-
- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
- page.load(request);
- QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::AlwaysCache);
-
- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
- page.load(request);
- QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::PreferCache);
-
- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
- page.load(request);
- QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::AlwaysNetwork);
-
- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork);
- page.load(request);
- QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::PreferNetwork);
-#endif
-}
-
-void tst_QWebEngineFrame::setUrlWithPendingLoads()
-{
- QWebEnginePage page;
- page.setHtml("<img src='dummy:'/>");
- page.setUrl(QUrl("about:blank"));
-}
-
-void tst_QWebEngineFrame::setUrlToEmpty()
-{
- int expectedLoadFinishedCount = 0;
- const QUrl aboutBlank("about:blank");
- const QUrl url("qrc:/test2.html");
-
- QWebEnginePage page;
- QCOMPARE(page.url(), QUrl());
- QCOMPARE(page.requestedUrl(), QUrl());
- QCOMPARE(baseUrlSync(&page), QUrl());
-
- QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
-
- // Set existing url
- page.setUrl(url);
- expectedLoadFinishedCount++;
- ::waitForSignal(&page, SIGNAL(loadFinished(bool)));
-
- QCOMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(page.url(), url);
- QCOMPARE(page.requestedUrl(), url);
- QCOMPARE(baseUrlSync(&page), url);
-
- // Set empty url
- page.setUrl(QUrl());
- expectedLoadFinishedCount++;
-
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(page.url(), aboutBlank);
- QCOMPARE(page.requestedUrl(), QUrl());
- QCOMPARE(baseUrlSync(&page), aboutBlank);
-
- // Set existing url
- page.setUrl(url);
- expectedLoadFinishedCount++;
-
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(page.url(), url);
- QCOMPARE(page.requestedUrl(), url);
- QCOMPARE(baseUrlSync(&page), url);
-
- // Load empty url
- page.load(QUrl());
- expectedLoadFinishedCount++;
-
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(page.url(), aboutBlank);
- QCOMPARE(page.requestedUrl(), QUrl());
- QCOMPARE(baseUrlSync(&page), aboutBlank);
-}
-
-void tst_QWebEngineFrame::setUrlToInvalid()
-{
- QEXPECT_FAIL("", "Unsupported: QtWebEngine doesn't adjust invalid URLs.", Abort);
- QVERIFY(false);
-
- QWebEnginePage page;
-
- const QUrl invalidUrl("http:/example.com");
- QVERIFY(!invalidUrl.isEmpty());
- QVERIFY(invalidUrl != QUrl());
-
- // QWebEngineFrame will do its best to accept the URL, possible converting it to a valid equivalent URL.
- const QUrl validUrl("http://example.com/");
- page.setUrl(invalidUrl);
- QCOMPARE(page.url(), validUrl);
- QCOMPARE(page.requestedUrl(), validUrl);
- QCOMPARE(baseUrlSync(&page), validUrl);
-
- // QUrls equivalent to QUrl() will be treated as such.
- const QUrl aboutBlank("about:blank");
- const QUrl anotherInvalidUrl("1http://bugs.webkit.org");
- QVERIFY(!anotherInvalidUrl.isEmpty()); // and they are not necessarily empty.
- QVERIFY(!anotherInvalidUrl.isValid());
- QCOMPARE(anotherInvalidUrl.toEncoded(), QUrl().toEncoded());
-
- page.setUrl(anotherInvalidUrl);
- QCOMPARE(page.url(), aboutBlank);
- QCOMPARE(page.requestedUrl().toEncoded(), anotherInvalidUrl.toEncoded());
- QCOMPARE(baseUrlSync(&page), aboutBlank);
-}
-
-static QStringList collectHistoryUrls(QWebEngineHistory *history)
-{
- QStringList urls;
- foreach (const QWebEngineHistoryItem &i, history->items())
- urls << i.url().toString();
- return urls;
-}
-
-void tst_QWebEngineFrame::setUrlHistory()
-{
- const QUrl aboutBlank("about:blank");
- QUrl url;
- int expectedLoadFinishedCount = 0;
- QSignalSpy spy(m_page, SIGNAL(loadFinished(bool)));
-
- QCOMPARE(m_page->history()->count(), 0);
-
- m_page->setUrl(QUrl());
- expectedLoadFinishedCount++;
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(m_page->url(), aboutBlank);
- QCOMPARE(m_page->requestedUrl(), QUrl());
- // Chromium stores navigation entry for every successful loads. The load of the empty page is committed and stored as about:blank.
- QCOMPARE(collectHistoryUrls(m_page->history()), QStringList() << aboutBlank.toString());
-
- url = QUrl("http://non.existent/");
- m_page->setUrl(url);
- expectedLoadFinishedCount++;
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- // When error page is disabled in case of LoadFail the entry of the unavailable page is not stored.
- // We expect the url of the previously loaded page here.
- QCOMPARE(m_page->url(), aboutBlank);
- QCOMPARE(m_page->requestedUrl(), QUrl());
- // Since the entry of the unavailable page is not stored it will not available in the history.
- QCOMPARE(collectHistoryUrls(m_page->history()), QStringList() << aboutBlank.toString());
-
- url = QUrl("qrc:/test1.html");
- m_page->setUrl(url);
- expectedLoadFinishedCount++;
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(m_page->url(), url);
- QCOMPARE(m_page->requestedUrl(), url);
- QCOMPARE(collectHistoryUrls(m_page->history()), QStringList() << aboutBlank.toString() << QStringLiteral("qrc:/test1.html"));
-
- m_page->setUrl(QUrl());
- expectedLoadFinishedCount++;
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(m_page->url(), aboutBlank);
- QCOMPARE(m_page->requestedUrl(), QUrl());
- // Chromium stores navigation entry for every successful loads. The load of the empty page is committed and stored as about:blank.
- QCOMPARE(collectHistoryUrls(m_page->history()), QStringList()
- << aboutBlank.toString()
- << QStringLiteral("qrc:/test1.html")
- << aboutBlank.toString());
-
- url = QUrl("qrc:/test1.html");
- m_page->setUrl(url);
- expectedLoadFinishedCount++;
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(m_page->url(), url);
- QCOMPARE(m_page->requestedUrl(), url);
- // The history count DOES change since the about:blank is in the list.
- QCOMPARE(collectHistoryUrls(m_page->history()), QStringList()
- << aboutBlank.toString()
- << QStringLiteral("qrc:/test1.html")
- << aboutBlank.toString()
- << QStringLiteral("qrc:/test1.html"));
-
- url = QUrl("qrc:/test2.html");
- m_page->setUrl(url);
- expectedLoadFinishedCount++;
- QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
- QCOMPARE(m_page->url(), url);
- QCOMPARE(m_page->requestedUrl(), url);
- QCOMPARE(collectHistoryUrls(m_page->history()), QStringList()
- << aboutBlank.toString()
- << QStringLiteral("qrc:/test1.html")
- << aboutBlank.toString()
- << QStringLiteral("qrc:/test1.html")
- << QStringLiteral("qrc:/test2.html"));
-}
-
-void tst_QWebEngineFrame::setUrlUsingStateObject()
-{
- const QUrl aboutBlank("about:blank");
- QUrl url;
- QSignalSpy urlChangedSpy(m_page, SIGNAL(urlChanged(QUrl)));
- int expectedUrlChangeCount = 0;
-
- QCOMPARE(m_page->history()->count(), 0);
-
- url = QUrl("qrc:/test1.html");
- m_page->setUrl(url);
- waitForSignal(m_page, SIGNAL(loadFinished(bool)));
- expectedUrlChangeCount++;
- QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
- QCOMPARE(m_page->url(), url);
- QCOMPARE(m_page->history()->count(), 1);
-
- evaluateJavaScriptSync(m_page, "window.history.pushState(null, 'push', 'navigate/to/here')");
- expectedUrlChangeCount++;
- QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
- QCOMPARE(m_page->url(), QUrl("qrc:/navigate/to/here"));
- QCOMPARE(m_page->history()->count(), 2);
- QVERIFY(m_page->history()->canGoBack());
-
- evaluateJavaScriptSync(m_page, "window.history.replaceState(null, 'replace', 'another/location')");
- expectedUrlChangeCount++;
- QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
- QCOMPARE(m_page->url(), QUrl("qrc:/navigate/to/another/location"));
- QCOMPARE(m_page->history()->count(), 2);
- QVERIFY(!m_page->history()->canGoForward());
- QVERIFY(m_page->history()->canGoBack());
-
- evaluateJavaScriptSync(m_page, "window.history.back()");
- QTest::qWait(100);
- expectedUrlChangeCount++;
- QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
- QCOMPARE(m_page->url(), QUrl("qrc:/test1.html"));
- QVERIFY(m_page->history()->canGoForward());
- QVERIFY(!m_page->history()->canGoBack());
-}
-
-void tst_QWebEngineFrame::setUrlSameUrl()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- const QUrl url1("qrc:/test1.html");
- const QUrl url2("qrc:/test2.html");
-
- QWebEnginePage page;
- FakeNetworkManager* networkManager = new FakeNetworkManager(&page);
- page.setNetworkAccessManager(networkManager);
-
- QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
-
- page.setUrl(url1);
- waitForSignal(&page, SIGNAL(loadFinished(bool)));
- QVERIFY(page.url() != url1); // Nota bene: our QNAM redirects url1 to url2
- QCOMPARE(page.url(), url2);
- QCOMPARE(spy.count(), 1);
-
- page.setUrl(url1);
- waitForSignal(&page, SIGNAL(loadFinished(bool)));
- QVERIFY(page.url() != url1);
- QCOMPARE(page.url(), url2);
- QCOMPARE(spy.count(), 2);
-
- // Now a case without redirect. The existing behavior we have for setUrl()
- // is more like a "clear(); load()", so the page will be loaded again, even
- // if urlToBeLoaded == url(). This test should be changed if we want to
- // make setUrl() early return in this case.
- page.setUrl(url2);
- waitForSignal(&page, SIGNAL(loadFinished(bool)));
- QCOMPARE(page.url(), url2);
- QCOMPARE(spy.count(), 3);
-
- page.setUrl(url1);
- waitForSignal(&page, SIGNAL(loadFinished(bool)));
- QCOMPARE(page.url(), url2);
- QCOMPARE(spy.count(), 4);
-#endif
-}
-
-static inline QUrl extractBaseUrl(const QUrl& url)
-{
- return url.resolved(QUrl());
-}
-
-void tst_QWebEngineFrame::setUrlThenLoads_data()
-{
- QTest::addColumn<QUrl>("url");
- QTest::addColumn<QUrl>("baseUrl");
-
- QTest::newRow("resource file") << QUrl("qrc:/test1.html") << extractBaseUrl(QUrl("qrc:/test1.html"));
- QTest::newRow("base specified in HTML") << QUrl("data:text/html,<head><base href=\"http://different.base/\"></head>") << QUrl("http://different.base/");
-}
-
-void tst_QWebEngineFrame::setUrlThenLoads()
-{
- QFETCH(QUrl, url);
- QFETCH(QUrl, baseUrl);
- QSignalSpy urlChangedSpy(m_page, SIGNAL(urlChanged(QUrl)));
- QSignalSpy startedSpy(m_page, SIGNAL(loadStarted()));
- QSignalSpy finishedSpy(m_page, SIGNAL(loadFinished(bool)));
-
- m_page->setUrl(url);
- QTRY_COMPARE(startedSpy.count(), 1);
- QTRY_COMPARE(urlChangedSpy.count(), 1);
- QTRY_COMPARE(finishedSpy.count(), 1);
- QVERIFY(finishedSpy.at(0).first().toBool());
- QCOMPARE(m_page->url(), url);
- QCOMPARE(m_page->requestedUrl(), url);
- QCOMPARE(baseUrlSync(m_page), baseUrl);
-
- const QUrl urlToLoad1("qrc:/test2.html");
- const QUrl urlToLoad2("qrc:/test1.html");
-
- // Just after first load. URL didn't changed yet.
- m_page->load(urlToLoad1);
- QCOMPARE(m_page->url(), url);
- QCOMPARE(m_page->requestedUrl(), urlToLoad1);
- // baseUrlSync spins an event loop and this sometimes return the next result.
- // QCOMPARE(baseUrlSync(m_page), baseUrl);
- QTRY_COMPARE(startedSpy.count(), 2);
-
- // After first URL changed.
- QTRY_COMPARE(urlChangedSpy.count(), 2);
- QTRY_COMPARE(finishedSpy.count(), 2);
- QVERIFY(finishedSpy.at(1).first().toBool());
- QCOMPARE(m_page->url(), urlToLoad1);
- QCOMPARE(m_page->requestedUrl(), urlToLoad1);
- QCOMPARE(baseUrlSync(m_page), extractBaseUrl(urlToLoad1));
-
- // Just after second load. URL didn't changed yet.
- m_page->load(urlToLoad2);
- QCOMPARE(m_page->url(), urlToLoad1);
- QCOMPARE(m_page->requestedUrl(), urlToLoad2);
- QCOMPARE(baseUrlSync(m_page), extractBaseUrl(urlToLoad1));
- QTRY_COMPARE(startedSpy.count(), 3);
-
- // After second URL changed.
- QTRY_COMPARE(urlChangedSpy.count(), 3);
- QTRY_COMPARE(finishedSpy.count(), 3);
- QVERIFY(finishedSpy.at(2).first().toBool());
- QCOMPARE(m_page->url(), urlToLoad2);
- QCOMPARE(m_page->requestedUrl(), urlToLoad2);
- QCOMPARE(baseUrlSync(m_page), extractBaseUrl(urlToLoad2));
-}
-
-void tst_QWebEngineFrame::loadFinishedAfterNotFoundError()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- QWebEnginePage page;
-
- QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
- FakeNetworkManager* networkManager = new FakeNetworkManager(&page);
- page.setNetworkAccessManager(networkManager);
-
- page.setUrl(FakeReply::urlFor404ErrorWithoutContents);
- QTRY_COMPARE(spy.count(), 1);
- const bool wasLoadOk = spy.at(0).at(0).toBool();
- QVERIFY(!wasLoadOk);
-#endif
-}
-
-class URLSetter : public QObject {
- Q_OBJECT
-
-public:
- enum Signal {
- LoadStarted,
- LoadFinished,
- ProvisionalLoad
- };
-
- enum Type {
- UseLoad,
- UseSetUrl
- };
-
- URLSetter(QWebEnginePage*, Signal, Type, const QUrl&);
-
-public Q_SLOTS:
- void execute();
-
-Q_SIGNALS:
- void finished();
-
-private:
- QWebEnginePage* m_page;
- QUrl m_url;
- Type m_type;
-};
-
-Q_DECLARE_METATYPE(URLSetter::Signal)
-Q_DECLARE_METATYPE(URLSetter::Type)
-
-URLSetter::URLSetter(QWebEnginePage* page, Signal signal, URLSetter::Type type, const QUrl& url)
- : m_page(page), m_url(url), m_type(type)
-{
- if (signal == LoadStarted)
- connect(m_page, SIGNAL(loadStarted()), SLOT(execute()));
- else if (signal == LoadFinished)
- connect(m_page, SIGNAL(loadFinished(bool)), SLOT(execute()));
- else
- connect(m_page, SIGNAL(provisionalLoad()), SLOT(execute()));
-}
-
-void URLSetter::execute()
-{
- // We track only the first emission.
- m_page->disconnect(this);
- if (m_type == URLSetter::UseLoad)
- m_page->load(m_url);
- else
- m_page->setUrl(m_url);
- connect(m_page, SIGNAL(loadFinished(bool)), SIGNAL(finished()));
-}
-
-void tst_QWebEngineFrame::loadInSignalHandlers_data()
-{
- QSKIP("FIXME: This crashes in content::WebContentsImpl::NavigateToEntry because of reentrancy. Should we require QueuedConnections or do it ourselves to support this?");
-
- QTest::addColumn<URLSetter::Type>("type");
- QTest::addColumn<URLSetter::Signal>("signal");
- QTest::addColumn<QUrl>("url");
-
- const QUrl validUrl("qrc:/test2.html");
- const QUrl invalidUrl("qrc:/invalid");
-
- QTest::newRow("call load() in loadStarted() after valid url") << URLSetter::UseLoad << URLSetter::LoadStarted << validUrl;
- QTest::newRow("call load() in loadStarted() after invalid url") << URLSetter::UseLoad << URLSetter::LoadStarted << invalidUrl;
- QTest::newRow("call load() in loadFinished() after valid url") << URLSetter::UseLoad << URLSetter::LoadFinished << validUrl;
- QTest::newRow("call load() in loadFinished() after invalid url") << URLSetter::UseLoad << URLSetter::LoadFinished << invalidUrl;
- QTest::newRow("call load() in provisionalLoad() after valid url") << URLSetter::UseLoad << URLSetter::ProvisionalLoad << validUrl;
- QTest::newRow("call load() in provisionalLoad() after invalid url") << URLSetter::UseLoad << URLSetter::ProvisionalLoad << invalidUrl;
-
- QTest::newRow("call setUrl() in loadStarted() after valid url") << URLSetter::UseSetUrl << URLSetter::LoadStarted << validUrl;
- QTest::newRow("call setUrl() in loadStarted() after invalid url") << URLSetter::UseSetUrl << URLSetter::LoadStarted << invalidUrl;
- QTest::newRow("call setUrl() in loadFinished() after valid url") << URLSetter::UseSetUrl << URLSetter::LoadFinished << validUrl;
- QTest::newRow("call setUrl() in loadFinished() after invalid url") << URLSetter::UseSetUrl << URLSetter::LoadFinished << invalidUrl;
- QTest::newRow("call setUrl() in provisionalLoad() after valid url") << URLSetter::UseSetUrl << URLSetter::ProvisionalLoad << validUrl;
- QTest::newRow("call setUrl() in provisionalLoad() after invalid url") << URLSetter::UseSetUrl << URLSetter::ProvisionalLoad << invalidUrl;
-}
-
-void tst_QWebEngineFrame::loadInSignalHandlers()
-{
- QFETCH(URLSetter::Type, type);
- QFETCH(URLSetter::Signal, signal);
- QFETCH(QUrl, url);
-
- const QUrl urlForSetter("qrc:/test1.html");
- URLSetter setter(m_page, signal, type, urlForSetter);
-
- m_page->load(url);
- waitForSignal(&setter, SIGNAL(finished()), 200);
- QCOMPARE(m_page->url(), urlForSetter);
-}
-
-QTEST_MAIN(tst_QWebEngineFrame)
-#include "tst_qwebengineframe.moc"
diff --git a/tests/auto/widgets/qwebengineframe/tst_qwebengineframe.qrc b/tests/auto/widgets/qwebengineframe/tst_qwebengineframe.qrc
deleted file mode 100644
index 2a7d0b9c2..000000000
--- a/tests/auto/widgets/qwebengineframe/tst_qwebengineframe.qrc
+++ /dev/null
@@ -1,10 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource prefix="/">
-<file alias="image.png">resources/image.png</file>
-<file alias="style.css">resources/style.css</file>
-<file alias="test1.html">resources/test1.html</file>
-<file alias="test2.html">resources/test2.html</file>
-<file alias="testiframe.html">resources/testiframe.html</file>
-<file alias="testiframe2.html">resources/testiframe2.html</file>
-</qresource>
-</RCC>
diff --git a/tests/auto/widgets/qwebenginehistory/qwebenginehistory.pro b/tests/auto/widgets/qwebenginehistory/qwebenginehistory.pro
index ff6c49628..e99c7f493 100644
--- a/tests/auto/widgets/qwebenginehistory/qwebenginehistory.pro
+++ b/tests/auto/widgets/qwebenginehistory/qwebenginehistory.pro
@@ -1,2 +1 @@
include(../tests.pri)
-exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
diff --git a/tests/auto/widgets/qwebenginehistoryinterface/qwebenginehistoryinterface.pro b/tests/auto/widgets/qwebenginehistoryinterface/qwebenginehistoryinterface.pro
index ff6c49628..e99c7f493 100644
--- a/tests/auto/widgets/qwebenginehistoryinterface/qwebenginehistoryinterface.pro
+++ b/tests/auto/widgets/qwebenginehistoryinterface/qwebenginehistoryinterface.pro
@@ -1,2 +1 @@
include(../tests.pri)
-exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
diff --git a/tests/auto/widgets/qwebengineinspector/qwebengineinspector.pro b/tests/auto/widgets/qwebengineinspector/qwebengineinspector.pro
index ff6c49628..e99c7f493 100644
--- a/tests/auto/widgets/qwebengineinspector/qwebengineinspector.pro
+++ b/tests/auto/widgets/qwebengineinspector/qwebengineinspector.pro
@@ -1,2 +1 @@
include(../tests.pri)
-exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
diff --git a/tests/auto/widgets/qwebenginepage/qwebenginepage.pro b/tests/auto/widgets/qwebenginepage/qwebenginepage.pro
index e56bbe8f7..70786e70f 100644
--- a/tests/auto/widgets/qwebenginepage/qwebenginepage.pro
+++ b/tests/auto/widgets/qwebenginepage/qwebenginepage.pro
@@ -1,3 +1,2 @@
include(../tests.pri)
-exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
QT *= core-private gui-private
diff --git a/tests/auto/widgets/qwebenginepage/resources/fullscreen.html b/tests/auto/widgets/qwebenginepage/resources/fullscreen.html
new file mode 100644
index 000000000..84771ca85
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepage/resources/fullscreen.html
@@ -0,0 +1,10 @@
+<html>
+<body onkeypress='onKeyPress()'>
+<a>This is test content</a>
+<script>
+function onKeyPress() {
+ document.documentElement.webkitRequestFullScreen();
+}
+</script>
+</body>
+</html>
diff --git a/tests/auto/widgets/qwebengineframe/resources/image.png b/tests/auto/widgets/qwebenginepage/resources/image.png
index 8d703640c..8d703640c 100644
--- a/tests/auto/widgets/qwebengineframe/resources/image.png
+++ b/tests/auto/widgets/qwebenginepage/resources/image.png
Binary files differ
diff --git a/tests/auto/widgets/qwebengineframe/resources/style.css b/tests/auto/widgets/qwebenginepage/resources/style.css
index c05b747f1..c05b747f1 100644
--- a/tests/auto/widgets/qwebengineframe/resources/style.css
+++ b/tests/auto/widgets/qwebenginepage/resources/style.css
diff --git a/tests/auto/widgets/qwebengineframe/resources/test1.html b/tests/auto/widgets/qwebenginepage/resources/test1.html
index b323f966e..b323f966e 100644
--- a/tests/auto/widgets/qwebengineframe/resources/test1.html
+++ b/tests/auto/widgets/qwebenginepage/resources/test1.html
diff --git a/tests/auto/widgets/qwebengineframe/resources/test2.html b/tests/auto/widgets/qwebenginepage/resources/test2.html
index 63ac1f6ec..63ac1f6ec 100644
--- a/tests/auto/widgets/qwebengineframe/resources/test2.html
+++ b/tests/auto/widgets/qwebenginepage/resources/test2.html
diff --git a/tests/auto/widgets/qwebengineframe/resources/testiframe.html b/tests/auto/widgets/qwebenginepage/resources/testiframe.html
index 4b0e30ca5..4b0e30ca5 100644
--- a/tests/auto/widgets/qwebengineframe/resources/testiframe.html
+++ b/tests/auto/widgets/qwebenginepage/resources/testiframe.html
diff --git a/tests/auto/widgets/qwebengineframe/resources/testiframe2.html b/tests/auto/widgets/qwebenginepage/resources/testiframe2.html
index 8957a5d8a..8957a5d8a 100644
--- a/tests/auto/widgets/qwebengineframe/resources/testiframe2.html
+++ b/tests/auto/widgets/qwebenginepage/resources/testiframe2.html
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 9562871b3..ffd8ccba7 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -27,6 +27,7 @@
#include <QMainWindow>
#include <QMenu>
#include <QMimeDatabase>
+#include <QPaintEngine>
#include <QPushButton>
#include <QStateMachine>
#include <QStyle>
@@ -37,8 +38,10 @@
#include <qnetworkreply.h>
#include <qnetworkrequest.h>
#include <qpa/qplatforminputcontext.h>
+#include <qwebenginefullscreenrequest.h>
#include <qwebenginehistory.h>
#include <qwebenginepage.h>
+#include <qwebengineprofile.h>
#include <qwebenginesettings.h>
#include <qwebengineview.h>
#include <qimagewriter.h>
@@ -95,6 +98,8 @@ public:
tst_QWebEnginePage();
virtual ~tst_QWebEnginePage();
+ bool eventFilter(QObject *watched, QEvent *event);
+
public Q_SLOTS:
void init();
void cleanup();
@@ -108,6 +113,7 @@ private Q_SLOTS:
void contextMenuPopulatedOnce();
void acceptNavigationRequest();
void acceptNavigationRequestNavigationType();
+ void geolocationRequestJS_data();
void geolocationRequestJS();
void loadFinished();
void actionStates();
@@ -132,7 +138,6 @@ private Q_SLOTS:
void textSelection();
void textEditing();
void backActionUpdate();
- void frameAt();
void protectBindingsRuntimeObjectsFromCollector();
void localURLSchemes();
void testOptionalJSObjects();
@@ -145,10 +150,7 @@ private Q_SLOTS:
void inputMethodsTextFormat();
void defaultTextEncoding();
void errorPageExtension();
- void errorPageExtensionInIFrames();
- void errorPageExtensionInFrameset();
void errorPageExtensionLoadFinished();
- void userAgentApplicationName();
void userAgentNewlineStripping();
void undoActionHaveCustomText();
void renderWidgetHostViewNotShowTopLevel();
@@ -166,9 +168,6 @@ private Q_SLOTS:
void unacceleratedWebGLScreenshotWithoutView();
#endif
- void originatingObjectInNetworkRequests();
- void networkReplyParentDidntChange();
- void destroyQNAMBeforeAbortDoesntCrash();
void testJSPrompt();
void testStopScheduledPageRefresh();
void findText();
@@ -192,10 +191,57 @@ private Q_SLOTS:
#endif
void runJavaScript();
+ void fullScreenRequested();
+
+
+ // Tests from tst_QWebEngineFrame
+ void horizontalScrollAfterBack();
+ void symmetricUrl();
+ void progressSignal();
+ void urlChange();
+ void requestedUrlAfterSetAndLoadFailures();
+ void javaScriptWindowObjectCleared_data();
+ void javaScriptWindowObjectCleared();
+ void javaScriptWindowObjectClearedOnEvaluate();
+ void asyncAndDelete();
+ void earlyToHtml();
+ void setHtml();
+ void setHtmlWithImageResource();
+ void setHtmlWithStylesheetResource();
+ void setHtmlWithBaseURL();
+ void setHtmlWithJSAlert();
+ void metaData();
+#if !defined(QT_NO_COMBOBOX)
+ void popupFocus();
+#endif
+ void inputFieldFocus();
+ void hitTestContent();
+ void baseUrl_data();
+ void baseUrl();
+ void renderHints();
+ void scrollPosition();
+ void scrollToAnchor();
+ void scrollbarsOff();
+ void evaluateWillCauseRepaint();
+ void setContent_data();
+ void setContent();
+ void setCacheLoadControlAttribute();
+ void setUrlWithPendingLoads();
+ void setUrlToEmpty();
+ void setUrlToInvalid();
+ void setUrlHistory();
+ void setUrlUsingStateObject();
+ void setUrlThenLoads_data();
+ void setUrlThenLoads();
+ void loadFinishedAfterNotFoundError();
+ void loadInSignalHandlers_data();
+ void loadInSignalHandlers();
private:
QWebEngineView* m_view;
QWebEnginePage* m_page;
+ QWebEngineView* m_inputFieldsTestView;
+ int m_inputFieldTestPaintCount;
QString tmpDirPath() const
{
static QString tmpd = QDir::tempPath() + "/tst_qwebenginepage-"
@@ -212,10 +258,21 @@ tst_QWebEnginePage::~tst_QWebEnginePage()
{
}
+bool tst_QWebEnginePage::eventFilter(QObject* watched, QEvent* event)
+{
+ // used on the inputFieldFocus test
+ if (watched == m_inputFieldsTestView) {
+ if (event->type() == QEvent::Paint)
+ m_inputFieldTestPaintCount++;
+ }
+ return QObject::eventFilter(watched, event);
+}
+
void tst_QWebEnginePage::init()
{
m_view = new QWebEngineView();
m_page = m_view->page();
+ m_page->settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
}
void tst_QWebEnginePage::cleanup()
@@ -278,7 +335,6 @@ void tst_QWebEnginePage::acceptNavigationRequest()
m_view->setPage(0);
}
-#if defined(QWEBENGINEPAGE_SETFEATUREPERMISSION)
class JSTestPage : public QWebEnginePage
{
Q_OBJECT
@@ -291,12 +347,12 @@ public:
return true;
}
public Q_SLOTS:
- void requestPermission(QWebEngineFrame* frame, QWebEnginePage::Feature feature)
+ void requestPermission(const QUrl &origin, QWebEnginePage::Feature feature)
{
if (m_allowGeolocation)
- setFeaturePermission(frame, feature, PermissionGrantedByUser);
+ setFeaturePermission(origin, feature, PermissionGrantedByUser);
else
- setFeaturePermission(frame, feature, PermissionDeniedByUser);
+ setFeaturePermission(origin, feature, PermissionDeniedByUser);
}
public:
@@ -308,7 +364,6 @@ public:
private:
bool m_allowGeolocation;
};
-#endif
// [Qt] tst_QWebEnginePage::infiniteLoopJS() timeouts with DFG JIT
// https://bugs.webkit.org/show_bug.cgi?id=79040
@@ -323,40 +378,38 @@ void tst_QWebEnginePage::infiniteLoopJS()
}
*/
-void tst_QWebEnginePage::geolocationRequestJS()
+void tst_QWebEnginePage::geolocationRequestJS_data()
{
-#if !defined(QWEBENGINEPAGE_SETFEATUREPERMISSION)
- QSKIP("QWEBENGINEPAGE_SETFEATUREPERMISSION");
-#else
- JSTestPage* newPage = new JSTestPage(m_view);
+ QTest::addColumn<bool>("allowed");
+ QTest::addColumn<int>("errorCode");
+ QTest::newRow("allowed") << true << 0;
+ QTest::newRow("not allowed") << false << 1;
+}
+void tst_QWebEnginePage::geolocationRequestJS()
+{
+ QFETCH(bool, allowed);
+ QFETCH(int, errorCode);
+ QWebEngineView *view = new QWebEngineView;
+ JSTestPage *newPage = new JSTestPage(view);
+ newPage->setView(view);
+ newPage->setGeolocationPermission(allowed);
+
+ connect(newPage, SIGNAL(featurePermissionRequested(const QUrl&, QWebEnginePage::Feature)),
+ newPage, SLOT(requestPermission(const QUrl&, QWebEnginePage::Feature)));
+
+ QSignalSpy spyLoadFinished(newPage, SIGNAL(loadFinished(bool)));
+ newPage->setHtml(QString("<html><body>test</body></html>"), QUrl());
+ QTRY_COMPARE(spyLoadFinished.count(), 1);
if (evaluateJavaScriptSync(newPage, QLatin1String("!navigator.geolocation")).toBool()) {
- delete newPage;
+ delete view;
W_QSKIP("Geolocation is not supported.", SkipSingle);
}
- connect(newPage, SIGNAL(featurePermissionRequested(QWebEngineFrame*, QWebEnginePage::Feature)),
- newPage, SLOT(requestPermission(QWebEngineFrame*, QWebEnginePage::Feature)));
-
- newPage->setGeolocationPermission(false);
- m_view->setPage(newPage);
- m_view->setHtml(QString("<html><body>test</body></html>"), QUrl());
- evaluateJavaScriptSync(m_view->page(), "var errorCode = 0; function error(err) { errorCode = err.code; } function success(pos) { } navigator.geolocation.getCurrentPosition(success, error)");
- QTest::qWait(2000);
- QVariant empty = evaluateJavaScriptSync(m_view->page(), "errorCode");
-
- QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=102235", Continue);
- QVERIFY(empty.type() == QVariant::Double && empty.toInt() != 0);
+ evaluateJavaScriptSync(newPage, "var errorCode = 0; function error(err) { errorCode = err.code; } function success(pos) { } navigator.geolocation.getCurrentPosition(success, error)");
- newPage->setGeolocationPermission(true);
- evaluateJavaScriptSync(m_view->page(), "errorCode = 0; navigator.geolocation.getCurrentPosition(success, error);");
- empty = evaluateJavaScriptSync(m_view->page(), "errorCode");
-
- //http://dev.w3.org/geo/api/spec-source.html#position
- //PositionError: const unsigned short PERMISSION_DENIED = 1;
- QVERIFY(empty.type() == QVariant::Double && empty.toInt() != 1);
- delete newPage;
-#endif
+ QTRY_COMPARE(evaluateJavaScriptSync(newPage, "errorCode").toInt(), errorCode);
+ delete view;
}
void tst_QWebEnginePage::loadFinished()
@@ -1176,6 +1229,10 @@ public:
int isSelectionCollapsed() {
return evaluateJavaScriptSync(this, "window.getSelection().getRangeAt(0).collapsed").toBool();
}
+ bool hasSelection()
+ {
+ return !selectedText().isEmpty();
+ }
};
void tst_QWebEnginePage::cursorMovements()
@@ -1380,17 +1437,19 @@ void tst_QWebEnginePage::cursorMovements()
void tst_QWebEnginePage::textSelection()
{
-#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
- QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
-#else
- CursorTrackedPage* page = new CursorTrackedPage;
+ QWebEngineView *view = new QWebEngineView;
+ CursorTrackedPage *page = new CursorTrackedPage;
QString content("<html><body><p id=one>The quick brown fox</p>" \
"<p id=two>jumps over the lazy dog</p>" \
"<p>May the source<br/>be with you!</p></body></html>");
+ page->setView(view);
+ QSignalSpy loadSpy(view, SIGNAL(loadFinished(bool)));
page->setHtml(content);
+ QTRY_COMPARE(loadSpy.count(), 1);
// these actions must exist
QVERIFY(page->action(QWebEnginePage::SelectAll) != 0);
+#if defined(QWEBENGINEPAGE_SELECTACTIONS)
QVERIFY(page->action(QWebEnginePage::SelectNextChar) != 0);
QVERIFY(page->action(QWebEnginePage::SelectPreviousChar) != 0);
QVERIFY(page->action(QWebEnginePage::SelectNextWord) != 0);
@@ -1418,6 +1477,7 @@ void tst_QWebEnginePage::textSelection()
QCOMPARE(page->action(QWebEnginePage::SelectEndOfBlock)->isEnabled(), false);
QCOMPARE(page->action(QWebEnginePage::SelectStartOfDocument)->isEnabled(), false);
QCOMPARE(page->action(QWebEnginePage::SelectEndOfDocument)->isEnabled(), false);
+#endif
// ..but SelectAll is awalys enabled
QCOMPARE(page->action(QWebEnginePage::SelectAll)->isEnabled(), true);
@@ -1432,13 +1492,15 @@ void tst_QWebEnginePage::textSelection()
"getSelection().addRange(range);";
evaluateJavaScriptSync(page, selectScript);
QCOMPARE(page->selectedText().trimmed(), QString::fromLatin1("The quick brown fox"));
+#if defined(QWEBENGINEPAGE_SELECTEDHTML)
QRegExp regExp(" style=\".*\"");
regExp.setMinimal(true);
QCOMPARE(page->selectedHtml().trimmed().replace(regExp, ""), QString::fromLatin1("<p id=\"one\">The quick brown fox</p>"));
-
+#endif
// Make sure hasSelection returns true, since there is selected text now...
QCOMPARE(page->hasSelection(), true);
+#if defined(QWEBENGINEPAGE_SELECTACTIONS)
// here the actions are enabled after a selection has been created
QCOMPARE(page->action(QWebEnginePage::SelectNextChar)->isEnabled(), true);
QCOMPARE(page->action(QWebEnginePage::SelectPreviousChar)->isEnabled(), true);
@@ -1474,9 +1536,10 @@ void tst_QWebEnginePage::textSelection()
QCOMPARE(page->action(QWebEnginePage::SelectEndOfBlock)->isEnabled(), true);
QCOMPARE(page->action(QWebEnginePage::SelectStartOfDocument)->isEnabled(), true);
QCOMPARE(page->action(QWebEnginePage::SelectEndOfDocument)->isEnabled(), true);
+#endif
delete page;
-#endif
+ delete view;
}
void tst_QWebEnginePage::textEditing()
@@ -1621,39 +1684,6 @@ void tst_QWebEnginePage::backActionUpdate()
QVERIFY(action->isEnabled());
}
-#if defined(QWEBENGINEFRAME)
-void frameAtHelper(QWebEnginePage* webPage, QWebEngineFrame* webFrame, QPoint framePosition)
-{
- if (!webFrame)
- return;
-
- framePosition += QPoint(webFrame->pos());
- QList<QWebEngineFrame*> children = webFrame->childFrames();
- for (int i = 0; i < children.size(); ++i) {
- if (children.at(i)->childFrames().size() > 0)
- frameAtHelper(webPage, children.at(i), framePosition);
-
- QRect frameRect(children.at(i)->pos() + framePosition, children.at(i)->geometry().size());
- QVERIFY(children.at(i) == webPage->frameAt(frameRect.topLeft()));
- }
-}
-#endif
-
-void tst_QWebEnginePage::frameAt()
-{
-#if !defined(QWEBENGINEFRAME)
- QSKIP("QWEBENGINEFRAME");
-#else
- QWebEngineView webView;
- QWebEnginePage* webPage = webView.page();
- QSignalSpy loadSpy(webPage, SIGNAL(loadFinished(bool)));
- QUrl url = QUrl("qrc:///resources/iframe.html");
- webPage->load(url);
- QTRY_COMPARE(loadSpy.count(), 1);
- frameAtHelper(webPage, webPage->mainFrame(), webPage->mainFrame()->pos());
-#endif
-}
-
void tst_QWebEnginePage::inputMethods_data()
{
QTest::addColumn<QString>("viewType");
@@ -2726,47 +2756,6 @@ void tst_QWebEnginePage::errorPageExtension()
#endif
}
-void tst_QWebEnginePage::errorPageExtensionInIFrames()
-{
-#if !defined(QWEBENGINEFRAME)
- QSKIP("QWEBENGINEFRAME");
-#else
- ErrorPage page;
- m_view->setPage(&page);
-
- m_view->page()->load(QUrl(
- "data:text/html,"
- "<h1>h1</h1>"
- "<iframe src='data:text/html,<p/>p'></iframe>"
- "<iframe src='http://non.existent/url'></iframe>"));
- QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool)));
- QTRY_COMPARE(spyLoadFinished.count(), 1);
-
- QCOMPARE(page.mainFrame()->childFrames()[1]->toPlainText(), QString("error"));
-
- m_view->setPage(0);
-#endif
-}
-
-void tst_QWebEnginePage::errorPageExtensionInFrameset()
-{
-#if !defined(QWEBENGINEFRAME)
- QSKIP("QWEBENGINEFRAME");
-#else
- ErrorPage page;
- m_view->setPage(&page);
-
- m_view->load(QUrl("qrc:///resources/index.html"));
-
- QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool)));
- QTRY_COMPARE(spyLoadFinished.count(), 1);
- QCOMPARE(page.mainFrame()->childFrames().count(), 2);
- QCOMPARE(page.mainFrame()->childFrames()[1]->toPlainText(), QString("error"));
-
- m_view->setPage(0);
-#endif
-}
-
void tst_QWebEnginePage::errorPageExtensionLoadFinished()
{
#if !defined(QWEBENGINEPAGE_ERRORPAGEEXTENSION)
@@ -2800,50 +2789,16 @@ void tst_QWebEnginePage::errorPageExtensionLoadFinished()
#endif
}
-class FriendlyWebPage : public QWebEnginePage
-{
-public:
- friend class tst_QWebEnginePage;
-};
-
-void tst_QWebEnginePage::userAgentApplicationName()
+void tst_QWebEnginePage::userAgentNewlineStripping()
{
-#if !defined(QWEBENGINEPAGE_USERAGENTFORURL)
- QSKIP("QWEBENGINEPAGE_USERAGENTFORURL");
-#else
- const QString oldApplicationName = QCoreApplication::applicationName();
- FriendlyWebPage page;
+ QWebEngineProfile profile;
+ QWebEnginePage page(&profile);
- const QString applicationNameMarker = QString::fromUtf8("StrangeName\342\210\236");
- QCoreApplication::setApplicationName(applicationNameMarker);
- QVERIFY(page.userAgentForUrl(QUrl()).contains(applicationNameMarker));
+ profile.setHttpUserAgent(QStringLiteral("My User Agent\nX-New-Http-Header: Oh Noes!"));
+ // The user agent will be updated after a page load.
+ page.load(QUrl("about:blank"));
- QCoreApplication::setApplicationName(oldApplicationName);
-#endif
-}
-
-class CustomUserAgentWebPage : public QWebEnginePage
-{
-public:
- static const QLatin1String filteredUserAgent;
-protected:
- virtual QString userAgentForUrl(const QUrl& url) const
- {
- Q_UNUSED(url);
- return QString("My User Agent\nX-New-Http-Header: Oh Noes!");
- }
-};
-const QLatin1String CustomUserAgentWebPage::filteredUserAgent("My User AgentX-New-Http-Header: Oh Noes!");
-
-void tst_QWebEnginePage::userAgentNewlineStripping()
-{
-#if !defined(QWEBENGINEPAGE_USERAGENTFORURL)
- QSKIP("QWEBENGINEPAGE_USERAGENTFORURL");
-#else
- CustomUserAgentWebPage page;
- page.setHtml("<html><body></body></html>");
- QCOMPARE(evaluateJavaScriptSync(&page, "navigator.userAgent").toString(), CustomUserAgentWebPage::filteredUserAgent);
-#endif
+ QCOMPARE(evaluateJavaScriptSync(&page, "navigator.userAgent").toString(), QStringLiteral("My User Agent X-New-Http-Header: Oh Noes!"));
}
void tst_QWebEnginePage::crashTests_LazyInitializationOfMainFrame()
@@ -2951,65 +2906,6 @@ void tst_QWebEnginePage::unacceleratedWebGLScreenshotWithoutView()
}
#endif
-void tst_QWebEnginePage::originatingObjectInNetworkRequests()
-{
-#if !defined(QWEBENGINEFRAME)
- QSKIP("QWEBENGINEFRAME");
-#else
- TestNetworkManager* networkManager = new TestNetworkManager(m_page);
- m_page->setNetworkAccessManager(networkManager);
- networkManager->requests.clear();
-
- m_view->setHtml(QString("<frameset cols=\"25%,75%\"><frame src=\"data:text/html,"
- "<head><meta http-equiv='refresh' content='1'></head>foo \">"
- "<frame src=\"data:text/html,bar\"></frameset>"), QUrl());
- QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool))));
-
- QCOMPARE(networkManager->requests.count(), 2);
-
- QList<QWebEngineFrame*> childFrames = m_page->mainFrame()->childFrames();
- QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118660", Continue);
- QCOMPARE(childFrames.count(), 2);
-
- for (int i = 0; i < 2; ++i)
- QVERIFY(qobject_cast<QWebEngineFrame*>(networkManager->requests.at(i).originatingObject()) == childFrames.at(i));
-#endif
-}
-
-void tst_QWebEnginePage::networkReplyParentDidntChange()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- TestNetworkManager* networkManager = new TestNetworkManager(m_page);
- m_page->setNetworkAccessManager(networkManager);
- networkManager->requests.clear();
-
- // Trigger a load and check that pending QNetworkReplies haven't been reparented before returning to the event loop.
- m_view->load(QUrl("qrc:///resources/content.html"));
-
- QVERIFY(networkManager->requests.count() > 0);
- QVERIFY(networkManager->findChildren<QNetworkReply*>().size() > 0);
-#endif
-}
-
-void tst_QWebEnginePage::destroyQNAMBeforeAbortDoesntCrash()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- QNetworkAccessManager* networkManager = new QNetworkAccessManager;
- m_page->setNetworkAccessManager(networkManager);
-
- m_view->load(QUrl("qrc:///resources/content.html"));
- delete networkManager;
- // This simulates what PingLoader does with its QNetworkReply when it times out.
- // PingLoader isn't attached to a QWebEnginePage and can be kept alive
- // for 60000 seconds (~16.7 hours) to then cancel its ResourceHandle.
- m_view->stop();
-#endif
-}
-
/**
* Test fixups for https://bugs.webkit.org/show_bug.cgi?id=30914
*
@@ -3109,13 +3005,16 @@ void tst_QWebEnginePage::testStopScheduledPageRefresh()
void tst_QWebEnginePage::findText()
{
- m_view->setHtml(QString("<html><head></head><body><div>foo bar</div></body></html>"));
-#if defined(QWEBENGINEPAGE_TRIGGERACTION_SELECTALL)
+ QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool)));
+ m_page->setHtml(QString("<html><head></head><body><div>foo bar</div></body></html>"));
+ QTRY_COMPARE(loadSpy.count(), 1);
m_page->triggerAction(QWebEnginePage::SelectAll);
- QVERIFY(!m_page->selectedText().isEmpty());
+ QTRY_COMPARE(m_page->hasSelection(), true);
+#if defined(QWEBENGINEPAGE_SELECTEDHTML)
QVERIFY(!m_page->selectedHtml().isEmpty());
#endif
m_page->findText("");
+ QEXPECT_FAIL("", "Unsupported: findText only highlights and doesn't update the selection.", Continue);
QVERIFY(m_page->selectedText().isEmpty());
#if defined(QWEBENGINEPAGE_SELECTEDHTML)
QVERIFY(m_page->selectedHtml().isEmpty());
@@ -3129,6 +3028,7 @@ void tst_QWebEnginePage::findText()
QVERIFY(m_page->selectedHtml().contains(subString));
#endif
m_page->findText("");
+ QEXPECT_FAIL("", "Unsupported: findText only highlights and doesn't update the selection.", Continue);
QVERIFY(m_page->selectedText().isEmpty());
#if defined(QWEBENGINEPAGE_SELECTEDHTML)
QVERIFY(m_page->selectedHtml().isEmpty());
@@ -3674,41 +3574,115 @@ void tst_QWebEnginePage::cssMediaTypePageSetting()
#endif
}
-class JavaScriptCallback
+class JavaScriptCallbackBase
+{
+public:
+ JavaScriptCallbackBase()
+ {
+ if (watcher)
+ QMetaObject::invokeMethod(watcher, "add");
+ }
+
+ void operator() (const QVariant &result)
+ {
+ check(result);
+ if (watcher)
+ QMetaObject::invokeMethod(watcher, "notify");
+ }
+
+protected:
+ virtual void check(const QVariant &result) = 0;
+
+private:
+ friend class JavaScriptCallbackWatcher;
+ static QPointer<QObject> watcher;
+};
+
+QPointer<QObject> JavaScriptCallbackBase::watcher = 0;
+
+class JavaScriptCallback : public JavaScriptCallbackBase
{
public:
JavaScriptCallback() { }
JavaScriptCallback(const QVariant& _expected) : expected(_expected) { }
- virtual void operator() (const QVariant& result) {
+
+ void check(const QVariant& result) Q_DECL_OVERRIDE
+ {
QVERIFY(result.isValid());
QCOMPARE(result, expected);
}
+
private:
QVariant expected;
};
-class JavaScriptCallbackNull
+class JavaScriptCallbackNull : public JavaScriptCallbackBase
{
public:
- virtual void operator() (const QVariant& result) {
+ void check(const QVariant& result) Q_DECL_OVERRIDE
+ {
QVERIFY(result.isNull());
// FIXME: Returned null values are currently invalid QVariants.
// QVERIFY(result.isValid());
}
};
-class JavaScriptCallbackUndefined
+class JavaScriptCallbackUndefined : public JavaScriptCallbackBase
{
public:
- virtual void operator() (const QVariant& result) {
+ void check(const QVariant& result) Q_DECL_OVERRIDE
+ {
QVERIFY(result.isNull());
QVERIFY(!result.isValid());
}
};
+class JavaScriptCallbackWatcher : public QObject
+{
+ Q_OBJECT
+public:
+ JavaScriptCallbackWatcher()
+ {
+ Q_ASSERT(!JavaScriptCallbackBase::watcher);
+ JavaScriptCallbackBase::watcher = this;
+ }
+
+ Q_INVOKABLE void add()
+ {
+ available++;
+ }
+
+ Q_INVOKABLE void notify()
+ {
+ called++;
+ if (called == available)
+ emit allCalled();
+ }
+
+ bool wait(int maxSeconds = 30)
+ {
+ if (called == available)
+ return true;
+
+ QTestEventLoop loop;
+ connect(this, SIGNAL(allCalled()), &loop, SLOT(exitLoop()));
+ loop.enterLoop(maxSeconds);
+ return !loop.timeout();
+ }
+
+signals:
+ void allCalled();
+
+private:
+ int available = 0;
+ int called = 0;
+};
+
+
void tst_QWebEnginePage::runJavaScript()
{
TestPage page;
+ JavaScriptCallbackWatcher watcher;
JavaScriptCallback callbackBool(QVariant(false));
page.runJavaScript("false", QWebEngineCallback<const QVariant&>(callbackBool));
@@ -3734,10 +3708,1363 @@ void tst_QWebEnginePage::runJavaScript()
JavaScriptCallbackNull callbackNull;
page.runJavaScript("null", QWebEngineCallback<const QVariant&>(callbackNull));
- JavaScriptCallbackNull callbackUndefined;
+ JavaScriptCallbackUndefined callbackUndefined;
page.runJavaScript("undefined", QWebEngineCallback<const QVariant&>(callbackUndefined));
+ QVERIFY(watcher.wait());
+}
+
+void tst_QWebEnginePage::fullScreenRequested()
+{
+ JavaScriptCallbackWatcher watcher;
+ QWebEnginePage* page = new QWebEnginePage;
+ QWebEngineView* view = new QWebEngineView;
+ view->setPage(page);
+ view->show();
+
+ page->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
+
+ QSignalSpy loadSpy(view, SIGNAL(loadFinished(bool)));
+ page->load(QUrl("qrc:///resources/fullscreen.html"));
+ QTRY_COMPARE(loadSpy.count(), 1);
+
+ page->runJavaScript("document.webkitFullscreenEnabled", JavaScriptCallback(true));
+ page->runJavaScript("document.webkitIsFullScreen", JavaScriptCallback(false));
+ QVERIFY(watcher.wait());
+
+ // FullscreenRequest must be a user gesture
+ bool acceptRequest = true;
+ connect(page, &QWebEnginePage::fullScreenRequested,
+ [&acceptRequest](const QWebEngineFullScreenRequest &request) {
+ if (acceptRequest) request.accept(); else request.reject();
+ });
+
+ QTest::keyPress(qApp->focusWindow(), Qt::Key_Space);
+ QTest::qWait(100);
+ page->runJavaScript("document.webkitIsFullScreen", JavaScriptCallback(true));
+ page->runJavaScript("document.webkitExitFullscreen()", JavaScriptCallbackUndefined());
+ QVERIFY(watcher.wait());
+
+ acceptRequest = false;
+
+ page->runJavaScript("document.webkitFullscreenEnabled", JavaScriptCallback(true));
+ QTest::keyPress(qApp->focusWindow(), Qt::Key_Space);
+ QVERIFY(watcher.wait());
+ page->runJavaScript("document.webkitIsFullScreen", JavaScriptCallback(false));
+ QVERIFY(watcher.wait());
+
+ delete view;
+ delete page;
+}
+
+void tst_QWebEnginePage::symmetricUrl()
+{
+ QWebEngineView view;
+ QSignalSpy loadFinishedSpy(view.page(), SIGNAL(loadFinished(bool)));
+
+ QVERIFY(view.url().isEmpty());
+
+ QCOMPARE(view.history()->count(), 0);
+
+ QUrl dataUrl("data:text/html,<h1>Test");
+
+ view.setUrl(dataUrl);
+ QCOMPARE(view.url(), dataUrl);
+ QCOMPARE(view.history()->count(), 0);
+
+ // loading is _not_ immediate, so the text isn't set just yet.
+ QVERIFY(toPlainTextSync(view.page()).isEmpty());
+
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+
+ QCOMPARE(view.history()->count(), 1);
+ QCOMPARE(toPlainTextSync(view.page()), QString("Test"));
+
+ QUrl dataUrl2("data:text/html,<h1>Test2");
+ QUrl dataUrl3("data:text/html,<h1>Test3");
+
+ view.setUrl(dataUrl2);
+ view.setUrl(dataUrl3);
+
+ QCOMPARE(view.url(), dataUrl3);
+
+ QTRY_VERIFY(loadFinishedSpy.count() >= 2);
+ QTRY_COMPARE(loadFinishedSpy.count(), 3);
+
+ QCOMPARE(view.history()->count(), 2);
+
+ QCOMPARE(toPlainTextSync(view.page()), QString("Test3"));
+}
+
+void tst_QWebEnginePage::progressSignal()
+{
+ QSignalSpy progressSpy(m_view, SIGNAL(loadProgress(int)));
+
+ QUrl dataUrl("data:text/html,<h1>Test");
+ m_view->setUrl(dataUrl);
+
+ ::waitForSignal(m_view, SIGNAL(loadFinished(bool)));
+
+ QVERIFY(progressSpy.size() >= 2);
+ int previousValue = -1;
+ for (QSignalSpy::ConstIterator it = progressSpy.begin(); it < progressSpy.end(); ++it) {
+ int current = (*it).first().toInt();
+ QVERIFY(current >= previousValue);
+ previousValue = current;
+ }
+
+ // But we always end at 100%
+ QCOMPARE(progressSpy.last().first().toInt(), 100);
+}
+
+void tst_QWebEnginePage::urlChange()
+{
+ QSignalSpy urlSpy(m_page, SIGNAL(urlChanged(QUrl)));
+
+ QUrl dataUrl("data:text/html,<h1>Test");
+ m_view->setUrl(dataUrl);
+
+ ::waitForSignal(m_page, SIGNAL(urlChanged(QUrl)));
+
+ QCOMPARE(urlSpy.size(), 1);
+
+ QUrl dataUrl2("data:text/html,<html><head><title>title</title></head><body><h1>Test</body></html>");
+ m_view->setUrl(dataUrl2);
+
+ ::waitForSignal(m_page, SIGNAL(urlChanged(QUrl)));
+
+ QCOMPARE(urlSpy.size(), 2);
+}
+
+class FakeReply : public QNetworkReply {
+ Q_OBJECT
+
+public:
+ static const QUrl urlFor404ErrorWithoutContents;
+
+ FakeReply(const QNetworkRequest& request, QObject* parent = 0)
+ : QNetworkReply(parent)
+ {
+ setOperation(QNetworkAccessManager::GetOperation);
+ setRequest(request);
+ setUrl(request.url());
+ if (request.url() == QUrl("qrc:/test1.html")) {
+ setHeader(QNetworkRequest::LocationHeader, QString("qrc:/test2.html"));
+ setAttribute(QNetworkRequest::RedirectionTargetAttribute, QUrl("qrc:/test2.html"));
+ QTimer::singleShot(0, this, SLOT(continueRedirect()));
+ }
+#ifndef QT_NO_OPENSSL
+ else if (request.url() == QUrl("qrc:/fake-ssl-error.html")) {
+ setError(QNetworkReply::SslHandshakeFailedError, tr("Fake error!"));
+ QTimer::singleShot(0, this, SLOT(continueError()));
+ }
+#endif
+ else if (request.url().host() == QLatin1String("abcdef.abcdef")) {
+ setError(QNetworkReply::HostNotFoundError, tr("Invalid URL"));
+ QTimer::singleShot(0, this, SLOT(continueError()));
+ } else if (request.url() == FakeReply::urlFor404ErrorWithoutContents) {
+ setError(QNetworkReply::ContentNotFoundError, "Not found");
+ setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 404);
+ QTimer::singleShot(0, this, SLOT(continueError()));
+ }
+
+ open(QIODevice::ReadOnly);
+ }
+ ~FakeReply()
+ {
+ close();
+ }
+ virtual void abort() {}
+ virtual void close() {}
+
+protected:
+ qint64 readData(char*, qint64)
+ {
+ return 0;
+ }
+
+private Q_SLOTS:
+ void continueRedirect()
+ {
+ emit metaDataChanged();
+ emit finished();
+ }
+
+ void continueError()
+ {
+ emit error(this->error());
+ emit finished();
+ }
+};
+
+const QUrl FakeReply::urlFor404ErrorWithoutContents = QUrl("http://this.will/return-http-404-error-without-contents.html");
+
+class FakeNetworkManager : public QNetworkAccessManager {
+ Q_OBJECT
+
+public:
+ FakeNetworkManager(QObject* parent) : QNetworkAccessManager(parent) { }
+
+protected:
+ virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
+ {
+ QString url = request.url().toString();
+ if (op == QNetworkAccessManager::GetOperation) {
+#ifndef QT_NO_OPENSSL
+ if (url == "qrc:/fake-ssl-error.html") {
+ FakeReply* reply = new FakeReply(request, this);
+ QList<QSslError> errors;
+ emit sslErrors(reply, errors << QSslError(QSslError::UnspecifiedError));
+ return reply;
+ }
+#endif
+ if (url == "qrc:/test1.html" || url == "http://abcdef.abcdef/" || request.url() == FakeReply::urlFor404ErrorWithoutContents)
+ return new FakeReply(request, this);
+ }
+
+ return QNetworkAccessManager::createRequest(op, request, outgoingData);
+ }
+};
+
+void tst_QWebEnginePage::requestedUrlAfterSetAndLoadFailures()
+{
+ QWebEnginePage page;
+ page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+ QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
+
+ const QUrl first("http://abcdef.abcdef/");
+ page.setUrl(first);
+ ::waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(page.url(), first);
+ QCOMPARE(page.requestedUrl(), first);
+ QVERIFY(!spy.at(0).first().toBool());
+
+ const QUrl second("http://abcdef.abcdef/another_page.html");
+ QVERIFY(first != second);
+
+ page.load(second);
+ ::waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(spy.count(), 2);
+ QCOMPARE(page.url(), first);
+ QCOMPARE(page.requestedUrl(), second);
+ QVERIFY(!spy.at(1).first().toBool());
+}
+
+void tst_QWebEnginePage::javaScriptWindowObjectCleared_data()
+{
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<int>("signalCount");
+ QTest::newRow("with <script>") << "<html><body><script>i=0</script><p>hello world</p></body></html>" << 1;
+ // NOTE: Empty scripts no longer cause this signal to be emitted.
+ QTest::newRow("with empty <script>") << "<html><body><script></script><p>hello world</p></body></html>" << 0;
+ QTest::newRow("without <script>") << "<html><body><p>hello world</p></body></html>" << 0;
+}
+
+void tst_QWebEnginePage::javaScriptWindowObjectCleared()
+{
+#if !defined(QWEBENGINEPAGE_JAVASCRIPTWINDOWOBJECTCLEARED)
+ QSKIP("QWEBENGINEPAGE_JAVASCRIPTWINDOWOBJECTCLEARED");
+#else
+ QWebEnginePage page;
+ QSignalSpy spy(&page, SIGNAL(javaScriptWindowObjectCleared()));
+ QFETCH(QString, html);
+ page.setHtml(html);
+
+ QFETCH(int, signalCount);
+ QCOMPARE(spy.count(), signalCount);
+#endif
+}
+
+void tst_QWebEnginePage::javaScriptWindowObjectClearedOnEvaluate()
+{
+#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
+ QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
+#else
+ QWebEnginePage page;
+ QSignalSpy spy(&page, SIGNAL(javaScriptWindowObjectCleared()));
+ page.setHtml("<html></html>");
+ QCOMPARE(spy.count(), 0);
+ page.evaluateJavaScript("var a = 'a';");
+ QCOMPARE(spy.count(), 1);
+ // no new clear for a new script:
+ page.evaluateJavaScript("var a = 1;");
+ QCOMPARE(spy.count(), 1);
+#endif
+}
+
+void tst_QWebEnginePage::asyncAndDelete()
+{
+ QWebEnginePage *page = new QWebEnginePage;
+ CallbackSpy<QString> plainTextSpy;
+ CallbackSpy<QString> htmlSpy;
+ page->toPlainText(plainTextSpy.ref());
+ page->toHtml(htmlSpy.ref());
+
+ delete page;
+ // Pending callbacks should be called with an empty value in the page's destructor.
+ QCOMPARE(plainTextSpy.waitForResult(), QString());
+ QVERIFY(plainTextSpy.wasCalled());
+ QCOMPARE(htmlSpy.waitForResult(), QString());
+ QVERIFY(htmlSpy.wasCalled());
+}
+
+void tst_QWebEnginePage::earlyToHtml()
+{
+ QString html("<html><head></head><body></body></html>");
+ QCOMPARE(toHtmlSync(m_view->page()), html);
+}
+
+void tst_QWebEnginePage::setHtml()
+{
+ QString html("<html><head></head><body><p>hello world</p></body></html>");
+ QSignalSpy spy(m_view->page(), SIGNAL(loadFinished(bool)));
+ m_view->page()->setHtml(html);
+ QVERIFY(spy.wait());
+ QCOMPARE(toHtmlSync(m_view->page()), html);
+}
+
+void tst_QWebEnginePage::setHtmlWithImageResource()
+{
+ // By default, only security origins of local files can load local resources.
+ // So we should specify baseUrl to be a local file in order to get a proper origin and load the local image.
+
+ QLatin1String html("<html><body><p>hello world</p><img src='qrc:/resources/image.png'/></body></html>");
+ QWebEnginePage page;
+
+ page.setHtml(html, QUrl(QLatin1String("file:///path/to/file")));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
+
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images.length").toInt(), 1);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 128);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 128);
+
+ // Now we test the opposite: without a baseUrl as a local file, we cannot request local resources.
+
+ page.setHtml(html);
+ waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images.length").toInt(), 1);
+ QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118659", Continue);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 0);
+ QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118659", Continue);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 0);
+}
+
+void tst_QWebEnginePage::setHtmlWithStylesheetResource()
+{
+#if !defined(QWEBENGINEELEMENT)
+ QSKIP("QWEBENGINEELEMENT");
+#else
+ // By default, only security origins of local files can load local resources.
+ // So we should specify baseUrl to be a local file in order to be able to download the local stylesheet.
+
+ const char* htmlData =
+ "<html>"
+ "<head>"
+ "<link rel='stylesheet' href='qrc:/style.css' type='text/css' />"
+ "</head>"
+ "<body>"
+ "<p id='idP'>some text</p>"
+ "</body>"
+ "</html>";
+ QLatin1String html(htmlData);
+ QWebEnginePage page;
+ QWebEngineElement webElement;
+
+ page.setHtml(html, QUrl(QLatin1String("qrc:///file")));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
+ webElement = page.documentElement().findFirst("p");
+ QCOMPARE(webElement.styleProperty("color", QWebEngineElement::CascadedStyle), QLatin1String("red"));
+
+ // Now we test the opposite: without a baseUrl as a local file, we cannot request local resources.
+
+ page.setHtml(html, QUrl(QLatin1String("http://www.example.com/")));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
+ webElement = page.documentElement().findFirst("p");
+ QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118659", Continue);
+ QCOMPARE(webElement.styleProperty("color", QWebEngineElement::CascadedStyle), QString());
+#endif
+}
+
+void tst_QWebEnginePage::setHtmlWithBaseURL()
+{
+ // This tests if baseUrl is indeed affecting the relative paths from resources.
+ // As we are using a local file as baseUrl, its security origin should be able to load local resources.
+
+ if (!QDir(TESTS_SOURCE_DIR).exists())
+ W_QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll);
+
+ QDir::setCurrent(TESTS_SOURCE_DIR);
+
+ QString html("<html><body><p>hello world</p><img src='resources/image2.png'/></body></html>");
+
+ QWebEnginePage page;
+
+ // in few seconds, the image should be completey loaded
+ QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
+
+ page.setHtml(html, QUrl::fromLocalFile(TESTS_SOURCE_DIR));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)), 200);
+ QCOMPARE(spy.count(), 1);
+
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images.length").toInt(), 1);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].width").toInt(), 128);
+ QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 128);
+
+ // no history item has to be added.
+ QCOMPARE(m_view->page()->history()->count(), 0);
+}
+
+class MyPage : public QWebEnginePage
+{
+public:
+ MyPage() : QWebEnginePage(), alerts(0) {}
+ int alerts;
+
+protected:
+ virtual void javaScriptAlert(const QUrl &securityOrigin, const QString &msg)
+ {
+ alerts++;
+ QCOMPARE(securityOrigin, QUrl(QStringLiteral("http://test.origin.com/")));
+ QCOMPARE(msg, QString("foo"));
+ }
+};
+
+void tst_QWebEnginePage::setHtmlWithJSAlert()
+{
+ QString html("<html><head></head><body><script>alert('foo');</script><p>hello world</p></body></html>");
+ MyPage page;
+ page.setHtml(html, QUrl(QStringLiteral("http://test.origin.com/path#fragment")));
+ waitForSignal(&page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(page.alerts, 1);
+ QCOMPARE(toHtmlSync(&page), html);
+}
+
+void tst_QWebEnginePage::metaData()
+{
+#if !defined(QWEBENGINEPAGE_METADATA)
+ QSKIP("QWEBENGINEPAGE_METADATA");
+#else
+ m_view->setHtml("<html>"
+ " <head>"
+ " <meta name=\"description\" content=\"Test description\">"
+ " <meta name=\"keywords\" content=\"HTML, JavaScript, Css\">"
+ " </head>"
+ "</html>");
+
+ QMultiMap<QString, QString> metaData = m_view->page()->metaData();
+
+ QCOMPARE(metaData.count(), 2);
+
+ QCOMPARE(metaData.value("description"), QString("Test description"));
+ QCOMPARE(metaData.value("keywords"), QString("HTML, JavaScript, Css"));
+ QCOMPARE(metaData.value("nonexistent"), QString());
+
+ m_view->setHtml("<html>"
+ " <head>"
+ " <meta name=\"samekey\" content=\"FirstValue\">"
+ " <meta name=\"samekey\" content=\"SecondValue\">"
+ " </head>"
+ "</html>");
+
+ metaData = m_view->page()->metaData();
+
+ QCOMPARE(metaData.count(), 2);
+
+ QStringList values = metaData.values("samekey");
+ QCOMPARE(values.count(), 2);
+
+ QVERIFY(values.contains("FirstValue"));
+ QVERIFY(values.contains("SecondValue"));
+
+ QCOMPARE(metaData.value("nonexistent"), QString());
+#endif
+}
+
+#if !defined(QT_NO_COMBOBOX)
+void tst_QWebEnginePage::popupFocus()
+{
+#if !defined(QWEBENGINEELEMENT)
+ QSKIP("QWEBENGINEELEMENT");
+#else
+ QWebEngineView view;
+ view.setHtml("<html>"
+ " <body>"
+ " <select name=\"select\">"
+ " <option>1</option>"
+ " <option>2</option>"
+ " </select>"
+ " <input type=\"text\"> </input>"
+ " <textarea name=\"text_area\" rows=\"3\" cols=\"40\">"
+ "This test checks whether showing and hiding a popup"
+ "takes the focus away from the webpage."
+ " </textarea>"
+ " </body>"
+ "</html>");
+ view.resize(400, 100);
+ // Call setFocus before show to work around http://bugreports.qt.nokia.com/browse/QTBUG-14762
+ view.setFocus();
+ view.show();
+ QTest::qWaitForWindowExposed(&view);
+ view.activateWindow();
+ QTRY_VERIFY(view.hasFocus());
+
+ // open the popup by clicking. check if focus is on the popup
+ const QWebEngineElement webCombo = view.page()->documentElement().findFirst(QLatin1String("select[name=select]"));
+ QTest::mouseClick(&view, Qt::LeftButton, 0, webCombo.geometry().center());
+
+ QComboBox* combo = view.findChild<QComboBox*>();
+ QVERIFY(combo != 0);
+ QTRY_VERIFY(!view.hasFocus() && combo->view()->hasFocus()); // Focus should be on the popup
+
+ // hide the popup and check if focus is on the page
+ combo->hidePopup();
+ QTRY_VERIFY(view.hasFocus()); // Focus should be back on the WebView
+#endif
+}
+#endif
+
+void tst_QWebEnginePage::inputFieldFocus()
+{
+#if !defined(QWEBENGINEELEMENT)
+ QSKIP("QWEBENGINEELEMENT");
+#else
+ QWebEngineView view;
+ view.setHtml("<html><body><input type=\"text\"></input></body></html>");
+ view.resize(400, 100);
+ view.show();
+ QTest::qWaitForWindowExposed(&view);
+ view.activateWindow();
+ view.setFocus();
+ QTRY_VERIFY(view.hasFocus());
+
+ // double the flashing time, should at least blink once already
+ int delay = qApp->cursorFlashTime() * 2;
+
+ // focus the lineedit and check if it blinks
+ bool autoSipEnabled = qApp->autoSipEnabled();
+ qApp->setAutoSipEnabled(false);
+ const QWebEngineElement inputElement = view.page()->documentElement().findFirst(QLatin1String("input[type=text]"));
+ QTest::mouseClick(&view, Qt::LeftButton, 0, inputElement.geometry().center());
+ m_inputFieldsTestView = &view;
+ view.installEventFilter( this );
+ QTest::qWait(delay);
+ QVERIFY2(m_inputFieldTestPaintCount >= 3,
+ "The input field should have a blinking caret");
+ qApp->setAutoSipEnabled(autoSipEnabled);
+#endif
+}
+
+void tst_QWebEnginePage::hitTestContent()
+{
+#if !defined(QWEBENGINEELEMENT)
+ QSKIP("QWEBENGINEELEMENT");
+#else
+ QString html("<html><body><p>A paragraph</p><br/><br/><br/><a href=\"about:blank\" target=\"_foo\" id=\"link\">link text</a></body></html>");
+
+ QWebEnginePage page;
+ page.setHtml(html);
+ page.setViewportSize(QSize(200, 0)); //no height so link is not visible
+ const QWebEngineElement linkElement = page.documentElement().findFirst(QLatin1String("a#link"));
+ QWebEngineHitTestResult result = page.hitTestContent(linkElement.geometry().center());
+ QCOMPARE(result.linkText(), QString("link text"));
+ QWebEngineElement link = result.linkElement();
+ QCOMPARE(link.attribute("target"), QString("_foo"));
+#endif
+}
+
+void tst_QWebEnginePage::baseUrl_data()
+{
+ QTest::addColumn<QString>("html");
+ QTest::addColumn<QUrl>("loadUrl");
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QUrl>("baseUrl");
+
+ QTest::newRow("null") << QString() << QUrl()
+ << QUrl("about:blank") << QUrl("about:blank");
+
+ QTest::newRow("foo") << QString() << QUrl("http://foobar.baz/")
+ << QUrl("http://foobar.baz/") << QUrl("http://foobar.baz/");
+
+ QString html = "<html>"
+ "<head>"
+ "<base href=\"http://foobaz.bar/\" />"
+ "</head>"
+ "</html>";
+ QTest::newRow("customBaseUrl") << html << QUrl("http://foobar.baz/")
+ << QUrl("http://foobar.baz/") << QUrl("http://foobaz.bar/");
+}
+
+void tst_QWebEnginePage::baseUrl()
+{
+ QFETCH(QString, html);
+ QFETCH(QUrl, loadUrl);
+ QFETCH(QUrl, url);
+ QFETCH(QUrl, baseUrl);
+
+ QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool)));
+ m_page->setHtml(html, loadUrl);
+ QTRY_COMPARE(loadSpy.count(), 1);
+ QCOMPARE(m_page->url(), url);
+ QEXPECT_FAIL("null", "Slight change: We now translate QUrl() to about:blank for the virtual url, but not for the baseUrl", Continue);
+ QCOMPARE(baseUrlSync(m_page), baseUrl);
+}
+
+class DummyPaintEngine: public QPaintEngine {
+public:
+
+ DummyPaintEngine()
+ : QPaintEngine(QPaintEngine::AllFeatures)
+ , renderHints(0)
+ {
+ }
+
+ bool begin(QPaintDevice*)
+ {
+ setActive(true);
+ return true;
+ }
+
+ bool end()
+ {
+ setActive(false);
+ return false;
+ }
+
+ void updateState(const QPaintEngineState& state)
+ {
+ renderHints = state.renderHints();
+ }
+
+ void drawPath(const QPainterPath&) { }
+ void drawPixmap(const QRectF&, const QPixmap&, const QRectF&) { }
+
+ QPaintEngine::Type type() const
+ {
+ return static_cast<QPaintEngine::Type>(QPaintEngine::User + 2);
+ }
+
+ QPainter::RenderHints renderHints;
+};
+
+class DummyPaintDevice: public QPaintDevice {
+public:
+ DummyPaintDevice()
+ : QPaintDevice()
+ , m_engine(new DummyPaintEngine)
+ {
+ }
+
+ ~DummyPaintDevice()
+ {
+ delete m_engine;
+ }
+
+ QPaintEngine* paintEngine() const
+ {
+ return m_engine;
+ }
+
+ QPainter::RenderHints renderHints() const
+ {
+ return m_engine->renderHints;
+ }
+
+protected:
+ int metric(PaintDeviceMetric metric) const;
+
+private:
+ DummyPaintEngine* m_engine;
+ friend class DummyPaintEngine;
+};
+
+
+int DummyPaintDevice::metric(PaintDeviceMetric metric) const
+{
+ switch (metric) {
+ case PdmWidth:
+ return 400;
+ break;
+
+ case PdmHeight:
+ return 200;
+ break;
+
+ case PdmNumColors:
+ return INT_MAX;
+ break;
+
+ case PdmDepth:
+ return 32;
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+void tst_QWebEnginePage::renderHints()
+{
+#if !defined(QWEBENGINEPAGE_RENDER)
+ QSKIP("QWEBENGINEPAGE_RENDER");
+#else
+ QString html("<html><body><p>Hello, world!</p></body></html>");
+
+ QWebEnginePage page;
+ page.setHtml(html);
+ page.setViewportSize(page.contentsSize());
+
+ // We will call frame->render and trap the paint engine state changes
+ // to ensure that GraphicsContext does not clobber the render hints.
+ DummyPaintDevice buffer;
+ QPainter painter(&buffer);
+
+ painter.setRenderHint(QPainter::TextAntialiasing, false);
+ page.render(&painter);
+ QVERIFY(!(buffer.renderHints() & QPainter::TextAntialiasing));
+ QVERIFY(!(buffer.renderHints() & QPainter::SmoothPixmapTransform));
+ QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
+
+ painter.setRenderHint(QPainter::TextAntialiasing, true);
+ page.render(&painter);
+ QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
+ QVERIFY(!(buffer.renderHints() & QPainter::SmoothPixmapTransform));
+ QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
+
+ painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
+ page.render(&painter);
+ QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
+ QVERIFY(buffer.renderHints() & QPainter::SmoothPixmapTransform);
+ QVERIFY(!(buffer.renderHints() & QPainter::HighQualityAntialiasing));
+
+ painter.setRenderHint(QPainter::HighQualityAntialiasing, true);
+ page.render(&painter);
+ QVERIFY(buffer.renderHints() & QPainter::TextAntialiasing);
+ QVERIFY(buffer.renderHints() & QPainter::SmoothPixmapTransform);
+ QVERIFY(buffer.renderHints() & QPainter::HighQualityAntialiasing);
+#endif
+}
+
+void tst_QWebEnginePage::scrollPosition()
+{
+#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
+ QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
+#else
+ // enlarged image in a small viewport, to provoke the scrollbars to appear
+ QString html("<html><body><img src='qrc:/image.png' height=500 width=500/></body></html>");
+
+ QWebEnginePage page;
+ page.setViewportSize(QSize(200, 200));
+
+ page.setHtml(html);
+ page.setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
+ page.setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
+
+ // try to set the scroll offset programmatically
+ page.setScrollPosition(QPoint(23, 29));
+ QCOMPARE(page.scrollPosition().x(), 23);
+ QCOMPARE(page.scrollPosition().y(), 29);
+
+ int x = page.evaluateJavaScript("window.scrollX").toInt();
+ int y = page.evaluateJavaScript("window.scrollY").toInt();
+ QCOMPARE(x, 23);
+ QCOMPARE(y, 29);
+#endif
+}
+
+void tst_QWebEnginePage::scrollToAnchor()
+{
+#if !defined(QWEBENGINEELEMENT)
+ QSKIP("QWEBENGINEELEMENT");
+#else
+ QWebEnginePage page;
+ page.setViewportSize(QSize(480, 800));
+
+ QString html("<html><body><p style=\"margin-bottom: 1500px;\">Hello.</p>"
+ "<p><a id=\"foo\">This</a> is an anchor</p>"
+ "<p style=\"margin-bottom: 1500px;\"><a id=\"bar\">This</a> is another anchor</p>"
+ "</body></html>");
+ page.setHtml(html);
+ page.setScrollPosition(QPoint(0, 0));
+ QCOMPARE(page.scrollPosition().x(), 0);
+ QCOMPARE(page.scrollPosition().y(), 0);
+
+ QWebEngineElement fooAnchor = page.findFirstElement("a[id=foo]");
+
+ page.scrollToAnchor("foo");
+ QCOMPARE(page.scrollPosition().y(), fooAnchor.geometry().top());
+
+ page.scrollToAnchor("bar");
+ page.scrollToAnchor("foo");
+ QCOMPARE(page.scrollPosition().y(), fooAnchor.geometry().top());
+
+ page.scrollToAnchor("top");
+ QCOMPARE(page.scrollPosition().y(), 0);
+
+ page.scrollToAnchor("bar");
+ page.scrollToAnchor("notexist");
+ QVERIFY(page.scrollPosition().y() != 0);
+#endif
+}
+
+
+void tst_QWebEnginePage::scrollbarsOff()
+{
+#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
+ QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
+#else
+ QWebEngineView view;
+ QWebEngineFrame* mainFrame = view.page();
+
+ mainFrame->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
+ mainFrame->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
+
+ QString html("<script>" \
+ " function checkScrollbar() {" \
+ " if (innerWidth === document.documentElement.offsetWidth)" \
+ " document.getElementById('span1').innerText = 'SUCCESS';" \
+ " else" \
+ " document.getElementById('span1').innerText = 'FAIL';" \
+ " }" \
+ "</script>" \
+ "<body>" \
+ " <div style='margin-top:1000px ; margin-left:1000px'>" \
+ " <a id='offscreen' href='a'>End</a>" \
+ " </div>" \
+ "<span id='span1'></span>" \
+ "</body>");
+
+
+ QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ view.setHtml(html);
+ ::waitForSignal(&view, SIGNAL(loadFinished(bool)), 200);
+ QCOMPARE(loadSpy.count(), 1);
+
+ mainFrame->evaluateJavaScript("checkScrollbar();");
+ QCOMPARE(mainFrame->documentElement().findAll("span").at(0).toPlainText(), QString("SUCCESS"));
+#endif
+}
+
+void tst_QWebEnginePage::horizontalScrollAfterBack()
+{
+#if !defined(QWEBENGINESETTINGS)
+ QSKIP("QWEBENGINESETTINGS");
+#else
+ QWebEngineView view;
+ QSignalSpy loadSpy(view.page(), SIGNAL(loadFinished(bool)));
+
+ view.page()->settings()->setMaximumPagesInCache(2);
+ view.page()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAsNeeded);
+ view.page()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAsNeeded);
+
+ view.load(QUrl("qrc:/resources/testiframe2.html"));
+ view.resize(200, 200);
+ QTRY_COMPARE(loadSpy.count(), 1);
+ QTRY_VERIFY((view.page()->scrollBarGeometry(Qt::Horizontal)).height());
+
+ view.load(QUrl("qrc:/resources/testiframe.html"));
+ QTRY_COMPARE(loadSpy.count(), 2);
+
+ view.page()->triggerAction(QWebEnginePage::Back);
+ QTRY_COMPARE(loadSpy.count(), 3);
+ QTRY_VERIFY((view.page()->scrollBarGeometry(Qt::Horizontal)).height());
+#endif
+}
+
+void tst_QWebEnginePage::evaluateWillCauseRepaint()
+{
+#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
+ QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
+#else
+ QWebEngineView view;
+ QString html("<html><body>top<div id=\"junk\" style=\"display: block;\">"
+ "junk</div>bottom</body></html>");
+ view.setHtml(html);
+ view.show();
+
+ QTest::qWaitForWindowExposed(&view);
+ view.page()->evaluateJavaScript(
+ "document.getElementById('junk').style.display = 'none';");
+
+ ::waitForSignal(view.page(), SIGNAL(repaintRequested(QRect)));
+#endif
+}
+
+void tst_QWebEnginePage::setContent_data()
+{
+ QTest::addColumn<QString>("mimeType");
+ QTest::addColumn<QByteArray>("testContents");
+ QTest::addColumn<QString>("expected");
+
+ QString str = QString::fromUtf8("ὕαλον ϕαγεῖν δύναμαι· τοῦτο οὔ με βλάπτει");
+ QTest::newRow("UTF-8 plain text") << "text/plain; charset=utf-8" << str.toUtf8() << str;
+
+ QTextCodec *utf16 = QTextCodec::codecForName("UTF-16");
+ if (utf16)
+ QTest::newRow("UTF-16 plain text") << "text/plain; charset=utf-16" << utf16->fromUnicode(str) << str;
+
+ str = QString::fromUtf8("Une chaîne de caractères à sa façon.");
+ QTest::newRow("latin-1 plain text") << "text/plain; charset=iso-8859-1" << str.toLatin1() << str;
+
+
+}
+
+void tst_QWebEnginePage::setContent()
+{
+ QFETCH(QString, mimeType);
+ QFETCH(QByteArray, testContents);
+ QFETCH(QString, expected);
+ QSignalSpy loadSpy(m_page, SIGNAL(loadFinished(bool)));
+ m_view->setContent(testContents, mimeType);
+ QVERIFY(loadSpy.wait());
+ QCOMPARE(toPlainTextSync(m_view->page()), expected);
+}
+
+class CacheNetworkAccessManager : public QNetworkAccessManager {
+public:
+ CacheNetworkAccessManager(QObject* parent = 0)
+ : QNetworkAccessManager(parent)
+ , m_lastCacheLoad(QNetworkRequest::PreferNetwork)
+ {
+ }
+
+ virtual QNetworkReply* createRequest(Operation, const QNetworkRequest& request, QIODevice*)
+ {
+ QVariant cacheLoad = request.attribute(QNetworkRequest::CacheLoadControlAttribute);
+ if (cacheLoad.isValid())
+ m_lastCacheLoad = static_cast<QNetworkRequest::CacheLoadControl>(cacheLoad.toUInt());
+ else
+ m_lastCacheLoad = QNetworkRequest::PreferNetwork; // default value
+ return new FakeReply(request, this);
+ }
+
+ QNetworkRequest::CacheLoadControl lastCacheLoad() const
+ {
+ return m_lastCacheLoad;
+ }
+
+private:
+ QNetworkRequest::CacheLoadControl m_lastCacheLoad;
+};
+
+void tst_QWebEnginePage::setCacheLoadControlAttribute()
+{
+#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
+ QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
+#else
+ QWebEnginePage page;
+ CacheNetworkAccessManager* manager = new CacheNetworkAccessManager(&page);
+ page.setNetworkAccessManager(manager);
+
+ QNetworkRequest request(QUrl("http://abcdef.abcdef/"));
+
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
+ page.load(request);
+ QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::AlwaysCache);
+
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
+ page.load(request);
+ QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::PreferCache);
+
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
+ page.load(request);
+ QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::AlwaysNetwork);
+
+ request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork);
+ page.load(request);
+ QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::PreferNetwork);
+#endif
+}
+
+void tst_QWebEnginePage::setUrlWithPendingLoads()
+{
+ QWebEnginePage page;
+ page.setHtml("<img src='dummy:'/>");
+ page.setUrl(QUrl("about:blank"));
+}
+
+void tst_QWebEnginePage::setUrlToEmpty()
+{
+ QSKIP("FIXME: [0908/090526:FATAL:navigation_controller_impl.cc(927)] Check failed: active_entry->site_instance() == rfh->GetSiteInstance().");
+
+ int expectedLoadFinishedCount = 0;
+ const QUrl aboutBlank("about:blank");
+ const QUrl url("qrc:/resources/test2.html");
+
+ QWebEnginePage page;
+ QCOMPARE(page.url(), QUrl());
+ QCOMPARE(page.requestedUrl(), QUrl());
+ QCOMPARE(baseUrlSync(&page), QUrl());
+
+ QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
+
+ // Set existing url
+ page.setUrl(url);
+ expectedLoadFinishedCount++;
+ ::waitForSignal(&page, SIGNAL(loadFinished(bool)));
+
+ QCOMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(page.url(), url);
+ QCOMPARE(page.requestedUrl(), url);
+ QCOMPARE(baseUrlSync(&page), url);
+
+ // Set empty url
+ page.setUrl(QUrl());
+ expectedLoadFinishedCount++;
+
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(page.url(), aboutBlank);
+ QCOMPARE(page.requestedUrl(), QUrl());
+ QCOMPARE(baseUrlSync(&page), aboutBlank);
+
+ // Set existing url
+ page.setUrl(url);
+ expectedLoadFinishedCount++;
+
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(page.url(), url);
+ QCOMPARE(page.requestedUrl(), url);
+ QCOMPARE(baseUrlSync(&page), url);
+
+ // Load empty url
+ page.load(QUrl());
+ expectedLoadFinishedCount++;
+
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(page.url(), aboutBlank);
+ QCOMPARE(page.requestedUrl(), QUrl());
+ QCOMPARE(baseUrlSync(&page), aboutBlank);
+}
+
+void tst_QWebEnginePage::setUrlToInvalid()
+{
+ QEXPECT_FAIL("", "Unsupported: QtWebEngine doesn't adjust invalid URLs.", Abort);
+ QVERIFY(false);
+
+ QWebEnginePage page;
+
+ const QUrl invalidUrl("http:/example.com");
+ QVERIFY(!invalidUrl.isEmpty());
+ QVERIFY(invalidUrl != QUrl());
+
+ // QWebEnginePage will do its best to accept the URL, possible converting it to a valid equivalent URL.
+ const QUrl validUrl("http://example.com/");
+ page.setUrl(invalidUrl);
+ QCOMPARE(page.url(), validUrl);
+ QCOMPARE(page.requestedUrl(), validUrl);
+ QCOMPARE(baseUrlSync(&page), validUrl);
+
+ // QUrls equivalent to QUrl() will be treated as such.
+ const QUrl aboutBlank("about:blank");
+ const QUrl anotherInvalidUrl("1http://bugs.webkit.org");
+ QVERIFY(!anotherInvalidUrl.isEmpty()); // and they are not necessarily empty.
+ QVERIFY(!anotherInvalidUrl.isValid());
+ QCOMPARE(anotherInvalidUrl.toEncoded(), QUrl().toEncoded());
+
+ page.setUrl(anotherInvalidUrl);
+ QCOMPARE(page.url(), aboutBlank);
+ QCOMPARE(page.requestedUrl().toEncoded(), anotherInvalidUrl.toEncoded());
+ QCOMPARE(baseUrlSync(&page), aboutBlank);
+}
+
+static QStringList collectHistoryUrls(QWebEngineHistory *history)
+{
+ QStringList urls;
+ foreach (const QWebEngineHistoryItem &i, history->items())
+ urls << i.url().toString();
+ return urls;
+}
+
+void tst_QWebEnginePage::setUrlHistory()
+{
+ QSKIP("FIXME: [0908/090526:FATAL:navigation_controller_impl.cc(927)] Check failed: active_entry->site_instance() == rfh->GetSiteInstance().");
+
+ const QUrl aboutBlank("about:blank");
+ QUrl url;
+ int expectedLoadFinishedCount = 0;
+ QSignalSpy spy(m_page, SIGNAL(loadFinished(bool)));
+
+ QCOMPARE(m_page->history()->count(), 0);
+
+ m_page->setUrl(QUrl());
+ expectedLoadFinishedCount++;
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(m_page->url(), aboutBlank);
+ QCOMPARE(m_page->requestedUrl(), QUrl());
+ // Chromium stores navigation entry for every successful loads. The load of the empty page is committed and stored as about:blank.
+ QCOMPARE(collectHistoryUrls(m_page->history()), QStringList() << aboutBlank.toString());
+
+ url = QUrl("http://non.existent/");
+ m_page->setUrl(url);
+ expectedLoadFinishedCount++;
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ // When error page is disabled in case of LoadFail the entry of the unavailable page is not stored.
+ // We expect the url of the previously loaded page here.
+ QCOMPARE(m_page->url(), aboutBlank);
+ QCOMPARE(m_page->requestedUrl(), QUrl());
+ // Since the entry of the unavailable page is not stored it will not available in the history.
+ QCOMPARE(collectHistoryUrls(m_page->history()), QStringList() << aboutBlank.toString());
+
+ url = QUrl("qrc:/resources/test1.html");
+ m_page->setUrl(url);
+ expectedLoadFinishedCount++;
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(m_page->url(), url);
+ QCOMPARE(m_page->requestedUrl(), url);
+ QCOMPARE(collectHistoryUrls(m_page->history()), QStringList() << aboutBlank.toString() << QStringLiteral("qrc:/resources/test1.html"));
+
+ m_page->setUrl(QUrl());
+ expectedLoadFinishedCount++;
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(m_page->url(), aboutBlank);
+ QCOMPARE(m_page->requestedUrl(), QUrl());
+ // Chromium stores navigation entry for every successful loads. The load of the empty page is committed and stored as about:blank.
+ QCOMPARE(collectHistoryUrls(m_page->history()), QStringList()
+ << aboutBlank.toString()
+ << QStringLiteral("qrc:/resources/test1.html")
+ << aboutBlank.toString());
+
+ url = QUrl("qrc:/resources/test1.html");
+ m_page->setUrl(url);
+ expectedLoadFinishedCount++;
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(m_page->url(), url);
+ QCOMPARE(m_page->requestedUrl(), url);
+ // The history count DOES change since the about:blank is in the list.
+ QCOMPARE(collectHistoryUrls(m_page->history()), QStringList()
+ << aboutBlank.toString()
+ << QStringLiteral("qrc:/resources/test1.html")
+ << aboutBlank.toString()
+ << QStringLiteral("qrc:/resources/test1.html"));
+
+ url = QUrl("qrc:/resources/test2.html");
+ m_page->setUrl(url);
+ expectedLoadFinishedCount++;
+ QTRY_COMPARE(spy.count(), expectedLoadFinishedCount);
+ QCOMPARE(m_page->url(), url);
+ QCOMPARE(m_page->requestedUrl(), url);
+ QCOMPARE(collectHistoryUrls(m_page->history()), QStringList()
+ << aboutBlank.toString()
+ << QStringLiteral("qrc:/resources/test1.html")
+ << aboutBlank.toString()
+ << QStringLiteral("qrc:/resources/test1.html")
+ << QStringLiteral("qrc:/resources/test2.html"));
+}
+
+void tst_QWebEnginePage::setUrlUsingStateObject()
+{
+ const QUrl aboutBlank("about:blank");
+ QUrl url;
+ QSignalSpy urlChangedSpy(m_page, SIGNAL(urlChanged(QUrl)));
+ int expectedUrlChangeCount = 0;
+
+ QCOMPARE(m_page->history()->count(), 0);
+
+ url = QUrl("qrc:/resources/test1.html");
+ m_page->setUrl(url);
+ waitForSignal(m_page, SIGNAL(loadFinished(bool)));
+ expectedUrlChangeCount++;
+ QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
+ QCOMPARE(m_page->url(), url);
+ QCOMPARE(m_page->history()->count(), 1);
+
+ evaluateJavaScriptSync(m_page, "window.history.pushState(null, 'push', 'navigate/to/here')");
+ expectedUrlChangeCount++;
+ QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
+ QCOMPARE(m_page->url(), QUrl("qrc:/resources/navigate/to/here"));
+ QCOMPARE(m_page->history()->count(), 2);
+ QVERIFY(m_page->history()->canGoBack());
+
+ evaluateJavaScriptSync(m_page, "window.history.replaceState(null, 'replace', 'another/location')");
+ expectedUrlChangeCount++;
+ QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
+ QCOMPARE(m_page->url(), QUrl("qrc:/resources/navigate/to/another/location"));
+ QCOMPARE(m_page->history()->count(), 2);
+ QVERIFY(!m_page->history()->canGoForward());
+ QVERIFY(m_page->history()->canGoBack());
+
+ evaluateJavaScriptSync(m_page, "window.history.back()");
QTest::qWait(100);
+ expectedUrlChangeCount++;
+ QCOMPARE(urlChangedSpy.count(), expectedUrlChangeCount);
+ QCOMPARE(m_page->url(), QUrl("qrc:/resources/test1.html"));
+ QVERIFY(m_page->history()->canGoForward());
+ QVERIFY(!m_page->history()->canGoBack());
+}
+
+static inline QUrl extractBaseUrl(const QUrl& url)
+{
+ return url.resolved(QUrl());
+}
+
+void tst_QWebEnginePage::setUrlThenLoads_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QUrl>("baseUrl");
+
+ QTest::newRow("resource file") << QUrl("qrc:/resources/test1.html") << extractBaseUrl(QUrl("qrc:/resources/test1.html"));
+ QTest::newRow("base specified in HTML") << QUrl("data:text/html,<head><base href=\"http://different.base/\"></head>") << QUrl("http://different.base/");
+}
+
+void tst_QWebEnginePage::setUrlThenLoads()
+{
+ QFETCH(QUrl, url);
+ QFETCH(QUrl, baseUrl);
+ QSignalSpy urlChangedSpy(m_page, SIGNAL(urlChanged(QUrl)));
+ QSignalSpy startedSpy(m_page, SIGNAL(loadStarted()));
+ QSignalSpy finishedSpy(m_page, SIGNAL(loadFinished(bool)));
+
+ m_page->setUrl(url);
+ QTRY_COMPARE(startedSpy.count(), 1);
+ QTRY_COMPARE(urlChangedSpy.count(), 1);
+ QTRY_COMPARE(finishedSpy.count(), 1);
+ QVERIFY(finishedSpy.at(0).first().toBool());
+ QCOMPARE(m_page->url(), url);
+ QCOMPARE(m_page->requestedUrl(), url);
+ QCOMPARE(baseUrlSync(m_page), baseUrl);
+
+ const QUrl urlToLoad1("qrc:/resources/test2.html");
+ const QUrl urlToLoad2("qrc:/resources/test1.html");
+
+ // Just after first load. URL didn't changed yet.
+ m_page->load(urlToLoad1);
+ QCOMPARE(m_page->url(), url);
+ QCOMPARE(m_page->requestedUrl(), urlToLoad1);
+ // baseUrlSync spins an event loop and this sometimes return the next result.
+ // QCOMPARE(baseUrlSync(m_page), baseUrl);
+ QTRY_COMPARE(startedSpy.count(), 2);
+
+ // After first URL changed.
+ QTRY_COMPARE(urlChangedSpy.count(), 2);
+ QTRY_COMPARE(finishedSpy.count(), 2);
+ QVERIFY(finishedSpy.at(1).first().toBool());
+ QCOMPARE(m_page->url(), urlToLoad1);
+ QCOMPARE(m_page->requestedUrl(), urlToLoad1);
+ QCOMPARE(baseUrlSync(m_page), extractBaseUrl(urlToLoad1));
+
+ // Just after second load. URL didn't changed yet.
+ m_page->load(urlToLoad2);
+ QCOMPARE(m_page->url(), urlToLoad1);
+ QCOMPARE(m_page->requestedUrl(), urlToLoad2);
+ QCOMPARE(baseUrlSync(m_page), extractBaseUrl(urlToLoad1));
+ QTRY_COMPARE(startedSpy.count(), 3);
+
+ // After second URL changed.
+ QTRY_COMPARE(urlChangedSpy.count(), 3);
+ QTRY_COMPARE(finishedSpy.count(), 3);
+ QVERIFY(finishedSpy.at(2).first().toBool());
+ QCOMPARE(m_page->url(), urlToLoad2);
+ QCOMPARE(m_page->requestedUrl(), urlToLoad2);
+ QCOMPARE(baseUrlSync(m_page), extractBaseUrl(urlToLoad2));
+}
+
+void tst_QWebEnginePage::loadFinishedAfterNotFoundError()
+{
+ QWebEnginePage page;
+ QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
+
+ page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+ page.setUrl(QUrl("http://non.existent/url"));
+ QTRY_COMPARE(spy.count(), 1);
+
+ page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, true);
+ page.setUrl(QUrl("http://another.non.existent/url"));
+ QTRY_COMPARE(spy.count(), 2);
+}
+
+class URLSetter : public QObject {
+ Q_OBJECT
+
+public:
+ enum Signal {
+ LoadStarted,
+ LoadFinished,
+ ProvisionalLoad
+ };
+
+ enum Type {
+ UseLoad,
+ UseSetUrl
+ };
+
+ URLSetter(QWebEnginePage*, Signal, Type, const QUrl&);
+
+public Q_SLOTS:
+ void execute();
+
+Q_SIGNALS:
+ void finished();
+
+private:
+ QWebEnginePage* m_page;
+ QUrl m_url;
+ Type m_type;
+};
+
+Q_DECLARE_METATYPE(URLSetter::Signal)
+Q_DECLARE_METATYPE(URLSetter::Type)
+
+URLSetter::URLSetter(QWebEnginePage* page, Signal signal, URLSetter::Type type, const QUrl& url)
+ : m_page(page), m_url(url), m_type(type)
+{
+ if (signal == LoadStarted)
+ connect(m_page, SIGNAL(loadStarted()), SLOT(execute()));
+ else if (signal == LoadFinished)
+ connect(m_page, SIGNAL(loadFinished(bool)), SLOT(execute()));
+ else
+ connect(m_page, SIGNAL(provisionalLoad()), SLOT(execute()));
+}
+
+void URLSetter::execute()
+{
+ // We track only the first emission.
+ m_page->disconnect(this);
+ if (m_type == URLSetter::UseLoad)
+ m_page->load(m_url);
+ else
+ m_page->setUrl(m_url);
+ connect(m_page, SIGNAL(loadFinished(bool)), SIGNAL(finished()));
+}
+
+void tst_QWebEnginePage::loadInSignalHandlers_data()
+{
+ QSKIP("FIXME: This crashes in content::WebContentsImpl::NavigateToEntry because of reentrancy. Should we require QueuedConnections or do it ourselves to support this?");
+
+ QTest::addColumn<URLSetter::Type>("type");
+ QTest::addColumn<URLSetter::Signal>("signal");
+ QTest::addColumn<QUrl>("url");
+
+ const QUrl validUrl("qrc:/resources/test2.html");
+ const QUrl invalidUrl("qrc:/invalid");
+
+ QTest::newRow("call load() in loadStarted() after valid url") << URLSetter::UseLoad << URLSetter::LoadStarted << validUrl;
+ QTest::newRow("call load() in loadStarted() after invalid url") << URLSetter::UseLoad << URLSetter::LoadStarted << invalidUrl;
+ QTest::newRow("call load() in loadFinished() after valid url") << URLSetter::UseLoad << URLSetter::LoadFinished << validUrl;
+ QTest::newRow("call load() in loadFinished() after invalid url") << URLSetter::UseLoad << URLSetter::LoadFinished << invalidUrl;
+ QTest::newRow("call load() in provisionalLoad() after valid url") << URLSetter::UseLoad << URLSetter::ProvisionalLoad << validUrl;
+ QTest::newRow("call load() in provisionalLoad() after invalid url") << URLSetter::UseLoad << URLSetter::ProvisionalLoad << invalidUrl;
+
+ QTest::newRow("call setUrl() in loadStarted() after valid url") << URLSetter::UseSetUrl << URLSetter::LoadStarted << validUrl;
+ QTest::newRow("call setUrl() in loadStarted() after invalid url") << URLSetter::UseSetUrl << URLSetter::LoadStarted << invalidUrl;
+ QTest::newRow("call setUrl() in loadFinished() after valid url") << URLSetter::UseSetUrl << URLSetter::LoadFinished << validUrl;
+ QTest::newRow("call setUrl() in loadFinished() after invalid url") << URLSetter::UseSetUrl << URLSetter::LoadFinished << invalidUrl;
+ QTest::newRow("call setUrl() in provisionalLoad() after valid url") << URLSetter::UseSetUrl << URLSetter::ProvisionalLoad << validUrl;
+ QTest::newRow("call setUrl() in provisionalLoad() after invalid url") << URLSetter::UseSetUrl << URLSetter::ProvisionalLoad << invalidUrl;
+}
+
+void tst_QWebEnginePage::loadInSignalHandlers()
+{
+ QFETCH(URLSetter::Type, type);
+ QFETCH(URLSetter::Signal, signal);
+ QFETCH(QUrl, url);
+
+ const QUrl urlForSetter("qrc:/resources/test1.html");
+ URLSetter setter(m_page, signal, type, urlForSetter);
+
+ m_page->load(url);
+ waitForSignal(&setter, SIGNAL(finished()), 200);
+ QCOMPARE(m_page->url(), urlForSetter);
}
QTEST_MAIN(tst_QWebEnginePage)
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
index 994d71b43..c7bffd5bb 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
@@ -1,5 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
+ <file>resources/content.html</file>
<file>resources/index.html</file>
<file>resources/frame_a.html</file>
<file>resources/frame_c.html</file>
@@ -7,8 +8,14 @@
<file>resources/iframe2.html</file>
<file>resources/iframe3.html</file>
<file>resources/framedindex.html</file>
- <file>resources/content.html</file>
+ <file>resources/fullscreen.html</file>
<file>resources/script.html</file>
<file>resources/user.css</file>
+ <file>resources/image.png</file>
+ <file>resources/style.css</file>
+ <file>resources/test1.html</file>
+ <file>resources/test2.html</file>
+ <file>resources/testiframe.html</file>
+ <file>resources/testiframe2.html</file>
</qresource>
</RCC>
diff --git a/tests/auto/widgets/qwebenginescript/qwebenginescript.pro b/tests/auto/widgets/qwebenginescript/qwebenginescript.pro
index ff6c49628..e99c7f493 100644
--- a/tests/auto/widgets/qwebenginescript/qwebenginescript.pro
+++ b/tests/auto/widgets/qwebenginescript/qwebenginescript.pro
@@ -1,2 +1 @@
include(../tests.pri)
-exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
diff --git a/tests/auto/widgets/qwebengineview/qwebengineview.pro b/tests/auto/widgets/qwebengineview/qwebengineview.pro
index ff6c49628..e99c7f493 100644
--- a/tests/auto/widgets/qwebengineview/qwebengineview.pro
+++ b/tests/auto/widgets/qwebengineview/qwebengineview.pro
@@ -1,2 +1 @@
include(../tests.pri)
-exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index 83f65f9d0..1ebb22cc9 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -25,6 +25,7 @@
#include <qpainter.h>
#include <qwebengineview.h>
#include <qwebenginepage.h>
+#include <qwebenginesettings.h>
#include <qnetworkrequest.h>
#include <qdiriterator.h>
@@ -148,9 +149,7 @@ void tst_QWebEngineView::reusePage()
QWebEngineView* view1 = new QWebEngineView;
QPointer<QWebEnginePage> page = new QWebEnginePage;
view1->setPage(page.data());
-#if defined(QWEBENGINESETTINGS)
page.data()->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
-#endif
page->setHtml(html, QUrl::fromLocalFile(TESTS_SOURCE_DIR));
if (html.contains("</embed>")) {
// some reasonable time for the PluginStream to feed test.swf to flash and start painting
diff --git a/tests/auto/widgets/tests.pri b/tests/auto/widgets/tests.pri
index 8d86ac93e..afdf46f42 100644
--- a/tests/auto/widgets/tests.pri
+++ b/tests/auto/widgets/tests.pri
@@ -11,6 +11,8 @@ TARGET = tst_$$TARGET
SOURCES += $${TARGET}.cpp
INCLUDEPATH += $$PWD
+exists($$_PRO_FILE_PWD_/$${TARGET}.qrc): RESOURCES += $${TARGET}.qrc
+
QT += testlib network webenginewidgets widgets
macx: CONFIG -= app_bundle
diff --git a/tests/auto/widgets/util.h b/tests/auto/widgets/util.h
index 83067fe8d..2b485fc0f 100644
--- a/tests/auto/widgets/util.h
+++ b/tests/auto/widgets/util.h
@@ -166,6 +166,9 @@ static inline QUrl baseUrlSync(QWebEnginePage *page)
#define W_QSKIP(a, b) QSKIP(a)
#define W_QTEST_MAIN(TestObject, params) \
+QT_BEGIN_NAMESPACE \
+QTEST_ADD_GPU_BLACKLIST_SUPPORT_DEFS \
+QT_END_NAMESPACE \
int main(int argc, char *argv[]) \
{ \
QVector<const char *> w_argv(argc); \
@@ -178,6 +181,8 @@ int main(int argc, char *argv[]) \
QApplication app(w_argc, const_cast<char **>(w_argv.data())); \
app.setAttribute(Qt::AA_Use96Dpi, true); \
QTEST_DISABLE_KEYPAD_NAVIGATION \
+ QTEST_ADD_GPU_BLACKLIST_SUPPORT \
TestObject tc; \
+ QTEST_SET_MAIN_SOURCE_PATH \
return QTest::qExec(&tc, argc, argv); \
}
diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro
index 2c8296cb8..aaafcb6e5 100644
--- a/tests/auto/widgets/widgets.pro
+++ b/tests/auto/widgets/widgets.pro
@@ -4,7 +4,6 @@ CONFIG += ordered
SUBDIRS += \
qwebengineaccessibility \
- qwebengineframe \
qwebenginepage \
qwebenginehistory \
qwebenginehistoryinterface \
diff --git a/tests/quicktestbrowser/ApplicationRoot.qml b/tests/quicktestbrowser/ApplicationRoot.qml
index 71737694d..5641b89a3 100644
--- a/tests/quicktestbrowser/ApplicationRoot.qml
+++ b/tests/quicktestbrowser/ApplicationRoot.qml
@@ -44,6 +44,8 @@ import QtWebEngine 1.1
QtObject {
id: root
+ property bool thirdPartyCookiesEnabled: true
+
property QtObject testProfile: WebEngineProfile {
storageName: "Test"
}
diff --git a/tests/quicktestbrowser/BrowserWindow.qml b/tests/quicktestbrowser/BrowserWindow.qml
index f93a6ccd1..3fcca4aab 100644
--- a/tests/quicktestbrowser/BrowserWindow.qml
+++ b/tests/quicktestbrowser/BrowserWindow.qml
@@ -39,7 +39,7 @@
****************************************************************************/
import QtQuick 2.1
-import QtWebEngine 1.1
+import QtWebEngine 1.2
import QtWebEngine.experimental 1.0
import QtQuick.Controls 1.0
@@ -61,8 +61,10 @@ ApplicationWindow {
// This is for the case where the system forces us to leave fullscreen.
if (currentWebView && !isFullScreen) {
currentWebView.state = ""
- if (currentWebView.isFullScreen)
+ if (currentWebView.isFullScreen) {
currentWebView.fullScreenCancelled()
+ fullScreenNotification.hide()
+ }
}
}
@@ -76,6 +78,8 @@ ApplicationWindow {
property alias autoLoadImages: loadImages.checked;
property alias javaScriptEnabled: javaScriptEnabled.checked;
property alias errorPageEnabled: errorPageEnabled.checked;
+ property alias pluginsEnabled: pluginsEnabled.checked;
+ property alias thirdPartyCookiesEnabled: thirdPartyCookiesEnabled.checked;
}
// Make sure the Qt.WindowFullscreenButtonHint is set on OS X.
@@ -245,6 +249,19 @@ ApplicationWindow {
checked: true
}
MenuItem {
+ id: pluginsEnabled
+ text: "Plugins On"
+ checkable: true
+ checked: true
+ }
+ MenuItem {
+ id: thirdPartyCookiesEnabled
+ text: "Third party cookies enabled"
+ checkable: true
+ checked: true
+ onToggled: applicationRoot.thirdPartyCookiesEnabled = checked
+ }
+ MenuItem {
id: offTheRecordEnabled
text: "Off The Record"
checkable: true
@@ -347,6 +364,7 @@ ApplicationWindow {
settings.autoLoadImages: appSettings.autoLoadImages
settings.javascriptEnabled: appSettings.javaScriptEnabled
settings.errorPageEnabled: appSettings.errorPageEnabled
+ settings.pluginsEnabled: appSettings.pluginsEnabled
onCertificateError: {
if (!acceptedCertificates.shouldAutoAccept(error)){
@@ -381,9 +399,11 @@ ApplicationWindow {
webEngineView.state = "FullScreen"
browserWindow.previousVisibility = browserWindow.visibility
browserWindow.showFullScreen()
+ fullScreenNotification.show()
} else {
webEngineView.state = ""
browserWindow.visibility = browserWindow.previousVisibility
+ fullScreenNotification.hide()
}
request.accept()
}
@@ -486,6 +506,10 @@ ApplicationWindow {
}
}
+ FullScreenNotification {
+ id: fullScreenNotification
+ }
+
DownloadView {
id: downloadView
visible: false
diff --git a/tests/quicktestbrowser/FullScreenNotification.qml b/tests/quicktestbrowser/FullScreenNotification.qml
new file mode 100644
index 000000000..80a63d479
--- /dev/null
+++ b/tests/quicktestbrowser/FullScreenNotification.qml
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+
+Rectangle {
+ id: fullScreenNotification
+ width: 500
+ height: 40
+ color: "white"
+ radius: 7
+
+ visible: false
+ opacity: 0
+
+ function show() {
+ visible = true
+ opacity = 1
+ reset.start()
+ }
+
+ function hide() {
+ reset.stop()
+ opacity = 0
+ }
+
+ Behavior on opacity {
+ NumberAnimation {
+ duration: 750
+ onStopped: {
+ if (opacity == 0)
+ visible = false
+ }
+ }
+ }
+
+ Timer {
+ id: reset
+ interval: 5000
+ onTriggered: hide()
+ }
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ y: 125
+
+ Text {
+ id: message
+ width: parent.width
+
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+
+ wrapMode: Text.WordWrap
+ elide: Text.ElideNone
+ clip: true
+
+ text: qsTr("You are now in fullscreen mode. Press ESC to quit!")
+ }
+}
diff --git a/tests/quicktestbrowser/main.cpp b/tests/quicktestbrowser/main.cpp
index 7171baf77..167f67dc3 100644
--- a/tests/quicktestbrowser/main.cpp
+++ b/tests/quicktestbrowser/main.cpp
@@ -50,7 +50,9 @@ typedef QGuiApplication Application;
#endif
#include <QtQml/QQmlApplicationEngine>
#include <QtQml/QQmlContext>
+#include <QtQml/QQmlComponent>
#include <QtWebEngine/qtwebengineglobal.h>
+#include <QtWebEngineCore/qwebenginecookiestoreclient.h>
static QUrl startupUrl()
{
@@ -80,7 +82,30 @@ int main(int argc, char **argv)
Utils utils;
appEngine.rootContext()->setContextProperty("utils", &utils);
appEngine.load(QUrl("qrc:/ApplicationRoot.qml"));
- QMetaObject::invokeMethod(appEngine.rootObjects().first(), "load", Q_ARG(QVariant, startupUrl()));
+ QObject *rootObject = appEngine.rootObjects().first();
+
+ QQmlComponent component(&appEngine);
+ component.setData(QByteArrayLiteral("import QtQuick 2.0\n"
+ "import QtWebEngine 1.1\n"
+ "WebEngineProfile {\n"
+ "storageName: \"Test\"\n"
+ "}")
+ , QUrl());
+ QObject *profile = component.create();
+ const QMetaObject *rootMeta = rootObject->metaObject();
+ QWebEngineCookieStoreClient *client = 0;
+ QMetaObject::invokeMethod(profile, "cookieStoreClient", Q_RETURN_ARG(QWebEngineCookieStoreClient*, client));
+ int index = rootMeta->indexOfProperty("thirdPartyCookiesEnabled");
+ Q_ASSERT(index != -1);
+ QMetaProperty thirdPartyCookiesProperty = rootMeta->property(index);
+ client->setCookieFilter([rootObject,&thirdPartyCookiesProperty](const QWebEngineCookieStoreClient::FilterRequest&){ return thirdPartyCookiesProperty.read(rootObject).toBool(); });
+
+ index = rootMeta->indexOfProperty("testProfile");
+ Q_ASSERT(index != -1);
+ QMetaProperty profileProperty = rootMeta->property(index);
+ profileProperty.write(rootObject, qVariantFromValue(profile));
+
+ QMetaObject::invokeMethod(rootObject, "load", Q_ARG(QVariant, startupUrl()));
return app.exec();
}
diff --git a/tests/quicktestbrowser/quicktestbrowser.pro b/tests/quicktestbrowser/quicktestbrowser.pro
index 7d6dfa6df..996e82a63 100644
--- a/tests/quicktestbrowser/quicktestbrowser.pro
+++ b/tests/quicktestbrowser/quicktestbrowser.pro
@@ -14,7 +14,8 @@ OTHER_FILES += ApplicationRoot.qml \
ButtonWithMenu.qml \
ContextMenuExtras.qml \
DownloadView.qml \
- FeaturePermissionBar.qml
+ FeaturePermissionBar.qml \
+ FullScreenNotification.qml
RESOURCES += resources.qrc
diff --git a/tests/quicktestbrowser/resources.qrc b/tests/quicktestbrowser/resources.qrc
index 80f1d1543..2dcda4d0d 100644
--- a/tests/quicktestbrowser/resources.qrc
+++ b/tests/quicktestbrowser/resources.qrc
@@ -5,6 +5,7 @@
<file>BrowserWindow.qml</file>
<file>ContextMenuExtras.qml</file>
<file>FeaturePermissionBar.qml</file>
+ <file>FullScreenNotification.qml</file>
<file>ButtonWithMenu.qml</file>
<file>DownloadView.qml</file>
<file>ZoomController.qml</file>