diff options
Diffstat (limited to 'tests')
25 files changed, 1299 insertions, 229 deletions
diff --git a/tests/auto/quick/inspectorserver/inspectorserver.pro b/tests/auto/quick/inspectorserver/inspectorserver.pro new file mode 100644 index 000000000..1a2c2f053 --- /dev/null +++ b/tests/auto/quick/inspectorserver/inspectorserver.pro @@ -0,0 +1,4 @@ +include(../tests.pri) +QT += webengine +QT_PRIVATE += webengine-private +DEFINES += IMPORT_DIR=\"\\\"$${ROOT_BUILD_DIR}$${QMAKE_DIR_SEP}imports\\\"\" diff --git a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp new file mode 100644 index 000000000..827f1a3c5 --- /dev/null +++ b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt 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 <QNetworkAccessManager> +#include <QNetworkReply> +#include <QNetworkRequest> +#include <QScopedPointer> +#include <QtQml/QQmlEngine> +#include <QtTest/QtTest> +#include <private/qquickwebengineview_p.h> + +#define INSPECTOR_SERVER_PORT "23654" +static const QUrl s_inspectorServerHttpBaseUrl("http://localhost:" INSPECTOR_SERVER_PORT); + +class tst_InspectorServer : public QObject { + Q_OBJECT +public: + tst_InspectorServer(); + +private Q_SLOTS: + void init(); + void cleanup(); + + void testPageList(); + void testRemoteDebuggingMessage(); + void openRemoteDebuggingSession(); +private: + void prepareWebViewComponent(); + inline QQuickWebEngineView* newWebView(); + inline QQuickWebEngineView* webView() const; + QJsonArray fetchPageList() const; + QScopedPointer<QQuickWebEngineView> m_webView; + QScopedPointer<QQmlComponent> m_component; +}; + +tst_InspectorServer::tst_InspectorServer() +{ + qputenv("QTWEBENGINE_REMOTE_DEBUGGING", INSPECTOR_SERVER_PORT); + QtWebEngine::initialize(); + prepareWebViewComponent(); +} + +void tst_InspectorServer::prepareWebViewComponent() +{ + static QQmlEngine* engine = new QQmlEngine(this); + engine->addImportPath(QString::fromUtf8(IMPORT_DIR)); + + m_component.reset(new QQmlComponent(engine, this)); + + m_component->setData(QByteArrayLiteral("import QtQuick 2.0\n" + "import QtWebEngine 1.0\n" + "WebEngineView { }") + , QUrl()); +} + +QQuickWebEngineView* tst_InspectorServer::newWebView() +{ + QObject* viewInstance = m_component->create(); + + return qobject_cast<QQuickWebEngineView*>(viewInstance); +} + +void tst_InspectorServer::init() +{ + m_webView.reset(newWebView()); +} + +void tst_InspectorServer::cleanup() +{ + m_webView.reset(); +} + +inline QQuickWebEngineView* tst_InspectorServer::webView() const +{ + return m_webView.data(); +} + +QJsonArray tst_InspectorServer::fetchPageList() const +{ + QNetworkAccessManager qnam; + QScopedPointer<QNetworkReply> reply(qnam.get(QNetworkRequest(s_inspectorServerHttpBaseUrl.resolved(QUrl("json/list"))))); + QSignalSpy(reply.data(), SIGNAL(finished())).wait(); + return QJsonDocument::fromJson(reply->readAll()).array(); +} + +void tst_InspectorServer::testPageList() +{ + const QUrl testPageUrl = QUrl::fromLocalFile(QLatin1String(TESTS_SOURCE_DIR "/html/basic_page.html")); + QSignalSpy loadSpy(webView(), SIGNAL(loadingChanged(QQuickWebEngineLoadRequest*))); + webView()->setUrl(testPageUrl); + QTRY_VERIFY(loadSpy.size() && !webView()->isLoading()); + + // Our page has developerExtrasEnabled and should be the only one in the list. + QJsonArray pageList = fetchPageList(); + QCOMPARE(pageList.size(), 1); + QCOMPARE(testPageUrl.toString(), pageList.at(0).toObject().value("url").toString()); +} + +void tst_InspectorServer::testRemoteDebuggingMessage() +{ + QJsonArray pageList = fetchPageList(); + QCOMPARE(pageList.size(), 1); + QVERIFY(pageList.at(0).toObject().contains("webSocketDebuggerUrl")); + + // Test sending a raw remote debugging message through our web socket server. + // For this specific message see: http://code.google.com/chrome/devtools/docs/protocol/tot/runtime.html#command-evaluate + QLatin1String jsExpression("2 + 2"); + QLatin1String jsExpressionResult("4"); + QScopedPointer<QQuickWebEngineView> webSocketQueryWebView(newWebView()); + webSocketQueryWebView->loadHtml(QString( + "<script type=\"text/javascript\">\n" + "var socket = new WebSocket('%1');\n" + "socket.onmessage = function(message) {\n" + "var response = JSON.parse(message.data);\n" + "if (response.id === 1)\n" + "document.title = response.result.result.value;\n" + "}\n" + "socket.onopen = function() {\n" + "socket.send('{\"id\": 1, \"method\": \"Runtime.evaluate\", \"params\": {\"expression\": \"%2\" } }');\n" + "}\n" + "</script>") + .arg(pageList.at(0).toObject().value("webSocketDebuggerUrl").toString()) + .arg(jsExpression)); + + QTRY_COMPARE(webSocketQueryWebView->title(), jsExpressionResult); +} + +void tst_InspectorServer::openRemoteDebuggingSession() +{ + QJsonArray pageList = fetchPageList(); + QCOMPARE(pageList.size(), 1); + QVERIFY(pageList.at(0).toObject().contains("devtoolsFrontendUrl")); + + QScopedPointer<QQuickWebEngineView> inspectorWebView(newWebView()); + inspectorWebView->setUrl(s_inspectorServerHttpBaseUrl.resolved(QUrl(pageList.at(0).toObject().value("devtoolsFrontendUrl").toString()))); + + // To test the whole pipeline this exploits a behavior of the inspector front-end which won't provide any title unless the + // debugging session was established correctly through web socket. + // So this test case will fail if: + // - The page list didn't return a valid inspector URL + // - Or the front-end couldn't be loaded through the inspector HTTP server + // - Or the web socket connection couldn't be established between the front-end and the page through the inspector server + QTRY_VERIFY(inspectorWebView->title().startsWith("Developer Tools -")); +} + +QTEST_MAIN(tst_InspectorServer) + +#include "tst_inspectorserver.moc" diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index f7cffb8b1..4b143d2bd 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -46,8 +46,12 @@ #include <QMetaType> #include <QtTest/QtTest> #include <private/qquickwebengineview_p.h> +#include <private/qquickwebenginecertificateerror_p.h> +#include <private/qquickwebenginedownloaditem_p.h> #include <private/qquickwebengineloadrequest_p.h> #include <private/qquickwebenginenavigationrequest_p.h> +#include <private/qquickwebenginenewviewrequest_p.h> +#include <private/qquickwebengineprofile_p.h> class tst_publicapi : public QObject { Q_OBJECT @@ -57,8 +61,12 @@ private Q_SLOTS: static QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *>() << &QQuickWebEngineView::staticMetaObject + << &QQuickWebEngineCertificateError::staticMetaObject + << &QQuickWebEngineDownloadItem::staticMetaObject << &QQuickWebEngineLoadRequest::staticMetaObject << &QQuickWebEngineNavigationRequest::staticMetaObject + << &QQuickWebEngineNewViewRequest::staticMetaObject + << &QQuickWebEngineProfile::staticMetaObject ; static QList<const char *> knownEnumNames = QList<const char *>(); @@ -74,6 +82,19 @@ static QStringList expectedAPI = QStringList() << "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" @@ -90,6 +111,7 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineView.NewViewInWindow --> NewViewDestination" << "QQuickWebEngineView.NewViewInTab --> NewViewDestination" << "QQuickWebEngineView.NewViewInDialog --> NewViewDestination" + << "QQuickWebEngineView.NewViewInBackgroundTab --> NewViewDestination" << "QQuickWebEngineView.InfoMessageLevel --> JavaScriptConsoleMessageLevel" << "QQuickWebEngineView.WarningMessageLevel --> JavaScriptConsoleMessageLevel" << "QQuickWebEngineView.ErrorMessageLevel --> JavaScriptConsoleMessageLevel" @@ -103,6 +125,7 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineView.titleChanged() --> void" << "QQuickWebEngineView.navigationHistoryChanged() --> void" << "QQuickWebEngineView.loadingChanged(QQuickWebEngineLoadRequest*) --> void" + << "QQuickWebEngineView.certificateError(QQuickWebEngineCertificateError*) --> void" << "QQuickWebEngineView.loadProgressChanged() --> void" << "QQuickWebEngineView.javaScriptConsoleMessage(JavaScriptConsoleMessageLevel,QString,int,QString) --> void" << "QQuickWebEngineView.urlChanged() --> void" @@ -117,6 +140,22 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineView.goForward() --> void" << "QQuickWebEngineView.stop() --> void" << "QQuickWebEngineView.reload() --> void" + << "QQuickWebEngineView.zoomFactor --> double" + << "QQuickWebEngineView.zoomFactorChanged(double) --> void" + << "QQuickWebEngineView.profile --> QQuickWebEngineProfile*" + << "QQuickWebEngineView.newViewRequested(QQuickWebEngineNewViewRequest*) --> void" + << "QQuickWebEngineDownloadItem.id --> uint" + << "QQuickWebEngineDownloadItem.state --> DownloadState" + << "QQuickWebEngineDownloadItem.progress --> int" + << "QQuickWebEngineDownloadItem.path --> QString" + << "QQuickWebEngineDownloadItem.DownloadInProgress --> DownloadState" + << "QQuickWebEngineDownloadItem.DownloadCompleted --> DownloadState" + << "QQuickWebEngineDownloadItem.DownloadCancelled --> DownloadState" + << "QQuickWebEngineDownloadItem.DownloadInterrupted --> DownloadState" + << "QQuickWebEngineDownloadItem.stateChanged() --> void" + << "QQuickWebEngineDownloadItem.progressChanged() --> void" + << "QQuickWebEngineDownloadItem.pathChanged() --> void" + << "QQuickWebEngineDownloadItem.cancel() --> void" << "QQuickWebEngineLoadRequest.url --> QUrl" << "QQuickWebEngineLoadRequest.status --> QQuickWebEngineView::LoadStatus" << "QQuickWebEngineLoadRequest.errorString --> QString" @@ -127,6 +166,39 @@ static QStringList expectedAPI = QStringList() << "QQuickWebEngineNavigationRequest.action --> QQuickWebEngineView::NavigationRequestAction" << "QQuickWebEngineNavigationRequest.navigationType --> QQuickWebEngineView::NavigationType" << "QQuickWebEngineNavigationRequest.actionChanged() --> void" + << "QQuickWebEngineNewViewRequest.destination --> QQuickWebEngineView::NewViewDestination" + << "QQuickWebEngineNewViewRequest.userInitiated --> bool" + << "QQuickWebEngineNewViewRequest.openIn(QQuickWebEngineView*) --> void" + << "QQuickWebEngineProfile.MemoryHttpCache --> HttpCacheType" + << "QQuickWebEngineProfile.DiskHttpCache --> HttpCacheType" + << "QQuickWebEngineProfile.NoPersistentCookies --> PersistentCookiesPolicy" + << "QQuickWebEngineProfile.AllowPersistentCookies --> PersistentCookiesPolicy" + << "QQuickWebEngineProfile.ForcePersistentCookies --> PersistentCookiesPolicy" + << "QQuickWebEngineProfile.storageName --> QString" + << "QQuickWebEngineProfile.offTheRecord --> bool" + << "QQuickWebEngineProfile.persistentStoragePath --> QString" + << "QQuickWebEngineProfile.cachePath --> QString" + << "QQuickWebEngineProfile.httpUserAgent --> QString" + << "QQuickWebEngineProfile.httpCacheType --> HttpCacheType" + << "QQuickWebEngineProfile.persistentCookiesPolicy --> PersistentCookiesPolicy" + << "QQuickWebEngineProfile.httpCacheMaxSize --> int" + << "QQuickWebEngineProfile.storageNameChanged() --> void" + << "QQuickWebEngineProfile.offTheRecordChanged() --> void" + << "QQuickWebEngineProfile.persistentStoragePathChanged() --> void" + << "QQuickWebEngineProfile.cachePathChanged() --> void" + << "QQuickWebEngineProfile.httpUserAgentChanged() --> void" + << "QQuickWebEngineProfile.httpCacheTypeChanged() --> void" + << "QQuickWebEngineProfile.persistentCookiesPolicyChanged() --> void" + << "QQuickWebEngineProfile.httpCacheMaxSizeChanged() --> void" + << "QQuickWebEngineCertificateError.ignoreCertificateError() --> void" + << "QQuickWebEngineCertificateError.rejectCertificate() --> void" + << "QQuickWebEngineCertificateError.defer() --> void" + << "QQuickWebEngineCertificateError.url --> QUrl" + << "QQuickWebEngineCertificateError.error --> Error" + << "QQuickWebEngineCertificateError.description --> QString" + << "QQuickWebEngineCertificateError.overridable --> bool" + << "QQuickWebEngineProfile.downloadStarted(QQuickWebEngineDownloadItem*) --> void" + << "QQuickWebEngineProfile.downloadFinished(QQuickWebEngineDownloadItem*) --> void" ; static bool isCheckedEnum(const QByteArray &typeName) diff --git a/tests/auto/quick/qmltests/data/keyboardModifierMapping.html b/tests/auto/quick/qmltests/data/keyboardModifierMapping.html new file mode 100644 index 000000000..b6d291207 --- /dev/null +++ b/tests/auto/quick/qmltests/data/keyboardModifierMapping.html @@ -0,0 +1,36 @@ +<html> +<body> +<kbd>Alt</kbd> is <span id="alt_state">no</span><br> +<kbd>Ctrl</kbd> is <span id="ctrl_state">no</span><br> +<kbd>Meta</kbd> is <span id="meta_state">no</span><br> +last keycode: <span id="last_keycode">none</span><br> + +<script> + +document.body.onkeydown = function(e) { + if (e.altKey) + alt_state.textContent = 'pressed' + if (e.ctrlKey) + ctrl_state.textContent = 'pressed' + if (e.metaKey) + meta_state.textContent = 'pressed' + last_keycode.textContent = e.keyCode +}; +document.body.onkeyup = function(e) { + if (e.altKey) + alt_state.textContent = 'released' + if (e.ctrlKey) + ctrl_state.textContent = 'released' + if (e.metaKey) + meta_state.textContent = 'released' + last_keycode.textContent = e.keyCode +}; + +function getPressedModifiers() { + return "alt:" + alt_state.textContent + " ctrl:" + ctrl_state.textContent + " meta:" + meta_state.textContent +} + +</script> +</body> +</html> + diff --git a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml new file mode 100644 index 000000000..ddf025281 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Quick Controls 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt 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.0 + +TestWebEngineView { + id: webEngineView + width: 400 + height: 300 + + SignalSpy { + id: spy + target: webEngineView + signalName: "titleChanged" + } + + TestCase { + name: "WebEngineViewKeyboardModifierMapping" + + when: false + Timer { + running: parent.windowShown + repeat: false + interval: 1 + onTriggered: parent.when = true + } + + function test_keyboardModifierMapping() { + webEngineView.url = Qt.resolvedUrl("keyboardModifierMapping.html") + waitForLoadSucceeded(); + var callbackCalled = false; + + // Alt + keyPress(Qt.Key_Alt); + runJavaScript("getPressedModifiers()", function(result) { + compare(result, "alt:pressed ctrl:no meta:no"); + callbackCalled = true; + }); + wait(100); + verify(callbackCalled); + keyRelease(Qt.Key_Alt) + callbackCalled = false; + + // Ctrl + // On mac Qt automatically translates Meta to Ctrl and vice versa. + // However, if sending the events manually no mapping is being done, + // so we have to do this here manually. + // For testing we assume that the flag Qt::AA_MacDontSwapCtrlAndMeta is NOT set. + keyPress(Qt.platform.os == "osx" ? Qt.Key_Meta : Qt.Key_Control); + runJavaScript("getPressedModifiers()", function(result) { + compare(result, "alt:released ctrl:pressed meta:no"); + callbackCalled = true; + }); + wait(100); + verify(callbackCalled); + keyRelease(Qt.platform.os == "osx" ? Qt.Key_Meta : Qt.Key_Control); + callbackCalled = false; + + // Meta (Command on Mac) + keyPress(Qt.platform.os == "osx" ? Qt.Key_Control : Qt.Key_Meta); + runJavaScript("getPressedModifiers()", function(result) { + compare(result, "alt:released ctrl:released meta:pressed"); + callbackCalled = true; + }); + wait(100); + verify(callbackCalled); + keyRelease(Qt.platform.os == "osx" ? Qt.Key_Control : Qt.Key_Meta); + callbackCalled = false; + + runJavaScript("getPressedModifiers()", function(result) { + compare(result, "alt:released ctrl:released meta:released"); + callbackCalled = true; + }); + wait(100); + verify(callbackCalled); + callbackCalled = false; + } + } +} diff --git a/tests/quicktestbrowser/util.h b/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml index bad41d6a7..f9b95ac19 100644 --- a/tests/quicktestbrowser/util.h +++ b/tests/auto/quick/qmltests/data/tst_loadRecursionCrash.qml @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** -** This file is part of the QtWebEngine module of the Qt Toolkit. +** This file is part of the Qt Quick Controls module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -38,36 +38,53 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef UTIL_H -#define UTIL_H -#include <QtCore/QCoreApplication> -#include <QtCore/QFileInfo> -#include <QtCore/QUrl> -#include <QtCore/QStringList> +import QtQuick 2.3 +import QtTest 1.0 +import QtWebEngine 1.0 -QUrl urlFromUserInput(const QString& userInput) -{ - QFileInfo fileInfo(userInput); - if (fileInfo.exists()) - return QUrl(fileInfo.absoluteFilePath()); - return QUrl::fromUserInput(userInput); -} - -QUrl startupUrl() -{ - QUrl ret; - QStringList args(qApp->arguments()); - args.takeFirst(); - Q_FOREACH (const QString& arg, args) { - if (arg.startsWith(QLatin1Char('-'))) - continue; - ret = urlFromUserInput(arg); - if (ret.isValid()) - return ret; +Item { +width: 300 +height: 400 + TextInput { + id: textInput + anchors { + top: parent.top + left: parent.left + right: parent.right + } + focus: true + text: Qt.resolvedUrl("test1.html") + onEditingFinished: webEngineView.url = text } - return QUrl(QStringLiteral("http://qt-project.org/")); -} + TestWebEngineView { + id: webEngineView + anchors { + top: textInput.bottom + left: parent.left + right: parent.right + bottom: parent.bottom + } -#endif // UTIL_H + TestCase { + name: "WebEngineViewLoadRecursionCrash" + when:windowShown + + function test_QTBUG_42929() { + textInput.forceActiveFocus() + keyClick(Qt.Key_Return) + verify(webEngineView.waitForLoadSucceeded()) + textInput.text = "about:blank" + textInput.forceActiveFocus() + keyClick(Qt.Key_Return) + verify(webEngineView.waitForLoadSucceeded()) + textInput.text = Qt.resolvedUrl("test4.html") + textInput.forceActiveFocus() + // Don't crash now + keyClick(Qt.Key_Return) + verify(webEngineView.waitForLoadSucceeded()) + } + } + } +} diff --git a/tests/quicktestbrowser/quickwindow.cpp b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml index ec7b6f94a..8d5fd5375 100644 --- a/tests/quicktestbrowser/quickwindow.cpp +++ b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml @@ -1,9 +1,9 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** -** This file is part of the QtWebEngine module of the Qt Toolkit. +** This file is part of the Qt Quick Controls module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -39,28 +39,57 @@ ** ****************************************************************************/ -#include "quickwindow.h" +import QtQuick 2.0 +import QtTest 1.0 +import QtWebEngine 1.0 -#include "util.h" +Item { + id: parentItem + width: 400 + height: 300 -#include <QFileInfo> -#include <QObject> -#include <QQmlContext> -#include <QQmlEngine> -#include <QUrl> + property var pressEvents: [] + property var releaseEvents: [] + Keys.onPressed: pressEvents.push(event.key) + Keys.onReleased: releaseEvents.push(event.key) -class Utils : public QObject { - Q_OBJECT -public: - Utils(QObject* parent = 0) : QObject(parent) { } - Q_INVOKABLE static QUrl fromUserInput(const QString& userInput) { return urlFromUserInput(userInput); } -}; + TestWebEngineView { + id: webEngineView + anchors.fill: parent + focus: true + } + TestCase { + name: "WebEngineViewUnhandledKeyEventPropagation" -#include "quickwindow.moc" + when: false + Timer { + running: parent.windowShown + repeat: false + interval: 1 + onTriggered: parent.when = true + } -ApplicationEngine::ApplicationEngine() -{ - rootContext()->setContextProperty("utils", new Utils(this)); - load(QUrl("qrc:/quickwindow.qml")); - QMetaObject::invokeMethod(rootObjects().first(), "load", Q_ARG(QVariant, startupUrl())); + function test_keyboardModifierMapping() { + webEngineView.loadHtml("<input type='text'/>") + webEngineView.waitForLoadSucceeded() + webEngineView.runJavaScript("document.body.firstChild.focus()") + + keyPress(Qt.Key_A) + keyRelease(Qt.Key_A) + keyPress(Qt.Key_Left) + keyRelease(Qt.Key_Left) + keyPress(Qt.Key_Left) + keyRelease(Qt.Key_Left) + + for (var i = 0; i < 20 && parentItem.releaseEvents.length < 3; i++) + wait(100) + + compare(parentItem.pressEvents.length, 1) + compare(parentItem.pressEvents[0], Qt.Key_Left) + compare(parentItem.releaseEvents.length, 3) + compare(parentItem.releaseEvents[0], Qt.Key_A) + compare(parentItem.releaseEvents[1], Qt.Key_Left) + compare(parentItem.releaseEvents[2], Qt.Key_Left) + } + } } diff --git a/tests/auto/quick/qmltests/data/tst_webchannel.qml b/tests/auto/quick/qmltests/data/tst_webchannel.qml new file mode 100644 index 000000000..1abb191e1 --- /dev/null +++ b/tests/auto/quick/qmltests/data/tst_webchannel.qml @@ -0,0 +1,114 @@ +/********************************************************************* +** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtWebChannel 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt 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.0 +import QtWebEngine.experimental 1.0 + +import QtWebChannel 1.0 + +Item { + id: test + signal barCalled(var arg) + signal clientInitializedCalled(var arg) + + QtObject { + id: testObject + WebChannel.id: "testObject" + + property var foo: 42 + + function clientInitialized(arg) + { + clientInitializedCalled(arg); + } + + function bar(arg) { + barCalled(arg); + } + + signal runTest(var foo) + } + + TestWebEngineView { + id: webView + experimental.webChannel.registeredObjects: [testObject] + } + + SignalSpy { + id: initializedSpy + target: test + signalName: "clientInitializedCalled" + } + + SignalSpy { + id: barSpy + target: test + signalName: "barCalled" + } + + TestCase { + name: "WebViewWebChannel" + property url testUrl: Qt.resolvedUrl("./webchannel-test.html") + + function init() { + initializedSpy.clear(); + barSpy.clear(); + } + + function test_basic() { + webView.url = testUrl; + verify(webView.waitForLoadSucceeded()); + + initializedSpy.wait(); + compare(initializedSpy.signalArguments.length, 1); + compare(initializedSpy.signalArguments[0][0], 42); + + var newValue = "roundtrip"; + testObject.runTest(newValue); + barSpy.wait(); + compare(barSpy.signalArguments.length, 1); + compare(barSpy.signalArguments[0][0], newValue); + + compare(testObject.foo, newValue); + } + } +} diff --git a/tests/auto/quick/qmltests/data/webchannel-test.html b/tests/auto/quick/qmltests/data/webchannel-test.html new file mode 100644 index 000000000..940821209 --- /dev/null +++ b/tests/auto/quick/qmltests/data/webchannel-test.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script> + <script type="text/javascript"> + //BEGIN SETUP + var channel = new QWebChannel(navigator.qtWebChannelTransport, function(channel) { + window.testObject = channel.objects.testObject; + testObject.runTest.connect(function(foo) { + testObject.foo = foo; + testObject.bar(foo); + }); + testObject.clientInitialized(testObject.foo); + }); + //END SETUP + </script> + </head> + <body> + </body> +</html> diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro index b40ef3b8c..6789b714b 100644 --- a/tests/auto/quick/qmltests/qmltests.pro +++ b/tests/auto/quick/qmltests/qmltests.pro @@ -16,6 +16,8 @@ OTHER_FILES += \ $$PWD/data/test1.html \ $$PWD/data/test2.html \ $$PWD/data/test3.html \ + $$PWD/data/test4.html \ + $$PWD/data/keyboardModifierMapping.html \ $$PWD/data/tst_desktopBehaviorLoadHtml.qml \ $$PWD/data/tst_favIconLoad.qml \ $$PWD/data/tst_linkHovered.qml \ @@ -23,12 +25,15 @@ OTHER_FILES += \ $$PWD/data/tst_loadHtml.qml \ $$PWD/data/tst_loadProgress.qml \ $$PWD/data/tst_loadProgressSignal.qml \ + $$PWD/data/tst_loadRecursionCrash.qml \ $$PWD/data/tst_loadUrl.qml \ $$PWD/data/tst_navigationHistory.qml \ $$PWD/data/tst_navigationRequested.qml \ $$PWD/data/tst_properties.qml \ $$PWD/data/tst_runJavaScript.qml \ - $$PWD/data/tst_titleChanged.qml + $$PWD/data/tst_titleChanged.qml \ + $$PWD/data/tst_keyboardModifierMapping.qml \ + load(qt_build_paths) DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$PWD$${QMAKE_DIR_SEP}data\\\"\" diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index 5c9bb72b5..71bc61b9e 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -1,6 +1,7 @@ TEMPLATE = subdirs SUBDIRS += \ + inspectorserver \ publicapi \ qmltests \ qquickwebengineview \ diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 6fb46057d..85939a686 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -107,11 +107,11 @@ private Q_SLOTS: void contextMenuCopy(); void contextMenuPopulatedOnce(); void acceptNavigationRequest(); + void acceptNavigationRequestNavigationType(); void geolocationRequestJS(); void loadFinished(); void actionStates(); void popupFormSubmission(); - void acceptNavigationRequestWithNewWindow(); void userStyleSheet(); void userStyleSheetFromLocalFileUrl(); void userStyleSheetFromQrcUrl(); @@ -133,8 +133,6 @@ private Q_SLOTS: void textEditing(); void backActionUpdate(); void frameAt(); - void requestCache(); - void loadCachedPage(); void protectBindingsRuntimeObjectsFromCollector(); void localURLSchemes(); void testOptionalJSObjects(); @@ -240,7 +238,6 @@ void tst_QWebEnginePage::cleanupTestCase() cleanupFiles(); // Be nice } -#if defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) class NavigationRequestOverride : public QWebEnginePage { public: @@ -248,21 +245,18 @@ public: bool m_acceptNavigationRequest; protected: - virtual bool acceptNavigationRequest(QWebEngineFrame* frame, const QNetworkRequest &request, QWebEnginePage::NavigationType type) { - Q_UNUSED(frame); - Q_UNUSED(request); + virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) + { + Q_UNUSED(url); Q_UNUSED(type); + Q_UNUSED(isMainFrame); return m_acceptNavigationRequest; } }; -#endif void tst_QWebEnginePage::acceptNavigationRequest() { -#if !defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) - QSKIP("QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST"); -#else QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool))); NavigationRequestOverride* newPage = new NavigationRequestOverride(m_view, false); @@ -278,11 +272,10 @@ void tst_QWebEnginePage::acceptNavigationRequest() evaluateJavaScriptSync(m_view->page(), "tstform.submit();"); QTRY_COMPARE(loadSpy.count(), 2); - QCOMPARE(m_view->page()->toPlainText(), QString("foo?")); + QCOMPARE(toPlainTextSync(m_view->page()), QString("foo?")); // Restore default page m_view->setPage(0); -#endif } #if defined(QWEBENGINEPAGE_SETFEATUREPERMISSION) @@ -439,23 +432,22 @@ public: connect(this, SIGNAL(geometryChangeRequested(QRect)), this, SLOT(slotGeometryChangeRequested(QRect))); } -#if defined(QWEBENGINEPAGE_ACCEPTNAVIGATIONREQUEST) struct Navigation { - QWebEngineFrame *frame; - QNetworkRequest request; NavigationType type; + QUrl url; + bool isMainFrame; }; QList<Navigation> navigations; - virtual bool acceptNavigationRequest(QWebEngineFrame* frame, const QNetworkRequest &request, NavigationType type) { + virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) + { Navigation n; - n.frame = frame; - n.request = request; + n.url = url; n.type = type; + n.isMainFrame = isMainFrame; navigations.append(n); return true; } -#endif QList<TestPage*> createdWindows; virtual QWebEnginePage* createWindow(WebWindowType) { @@ -471,6 +463,42 @@ private Q_SLOTS: } }; +void tst_QWebEnginePage::acceptNavigationRequestNavigationType() +{ + + TestPage page; + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + + page.load(QUrl("qrc:///resources/script.html")); + QTRY_COMPARE(loadSpy.count(), 1); + QTRY_COMPARE(page.navigations.count(), 1); + + page.load(QUrl("qrc:///resources/content.html")); + QTRY_COMPARE(loadSpy.count(), 2); + QTRY_COMPARE(page.navigations.count(), 2); + + page.triggerAction(QWebEnginePage::Stop); + QVERIFY(page.history()->canGoBack()); + page.triggerAction(QWebEnginePage::Back); + + QTRY_COMPARE(loadSpy.count(), 3); + QTRY_COMPARE(page.navigations.count(), 3); + + page.triggerAction(QWebEnginePage::Reload); + QTRY_COMPARE(loadSpy.count(), 4); + QTRY_COMPARE(page.navigations.count(), 4); + + QList<QWebEnginePage::NavigationType> expectedList; + expectedList << QWebEnginePage::NavigationTypeTyped + << QWebEnginePage::NavigationTypeTyped + << QWebEnginePage::NavigationTypeBackForward + << QWebEnginePage::NavigationTypeReload; + QVERIFY(expectedList.count() == page.navigations.count()); + for (int i = 0; i < expectedList.count(); ++i) { + QCOMPARE(page.navigations[i].type, expectedList[i]); + } +} + void tst_QWebEnginePage::popupFormSubmission() { TestPage page; @@ -491,38 +519,6 @@ void tst_QWebEnginePage::popupFormSubmission() QVERIFY(url.contains("?foo=bar")); } -void tst_QWebEnginePage::acceptNavigationRequestWithNewWindow() -{ -#if !defined(QWEBENGINESETTINGS) - QSKIP("QWEBENGINESETTINGS"); -#else - TestPage* page = new TestPage(m_view); - page->settings()->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain, true); - m_page = page; - m_view->setPage(m_page); - - m_view->setUrl(QString("data:text/html,<a href=\"data:text/html,Reached\" target=\"_blank\">Click me</a>")); - QVERIFY(::waitForSignal(m_view, SIGNAL(loadFinished(bool)))); - - QFocusEvent fe(QEvent::FocusIn); - m_page->event(&fe); - - QVERIFY(m_page->focusNextPrevChild(/*next*/ true)); - - QKeyEvent keyEnter(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier); - m_page->event(&keyEnter); - - QCOMPARE(page->navigations.count(), 2); - - TestPage::Navigation n = page->navigations.at(1); - QVERIFY(!n.frame); - QCOMPARE(n.request.url().toString(), QString("data:text/html,Reached")); - QVERIFY(n.type == QWebEnginePage::NavigationTypeLinkClicked); - - QCOMPARE(page->createdWindows.count(), 1); -#endif -} - class TestNetworkManager : public QNetworkAccessManager { public: @@ -1606,72 +1602,6 @@ void tst_QWebEnginePage::textEditing() #endif } -void tst_QWebEnginePage::requestCache() -{ -#if !defined(ACCEPTNAVIGATIONREQUEST) - QSKIP("ACCEPTNAVIGATIONREQUEST"); -#else - TestPage page; - QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); - - page.setUrl(QString("data:text/html,<a href=\"data:text/html,Reached\" target=\"_blank\">Click me</a>")); - QTRY_COMPARE(loadSpy.count(), 1); - QTRY_COMPARE(page.navigations.count(), 1); - - page.setUrl(QString("data:text/html,<a href=\"data:text/html,Reached\" target=\"_blank\">Click me2</a>")); - QTRY_COMPARE(loadSpy.count(), 2); - QTRY_COMPARE(page.navigations.count(), 2); - - page.triggerAction(QWebEnginePage::Stop); - QVERIFY(page.history()->canGoBack()); - page.triggerAction(QWebEnginePage::Back); - - QTRY_COMPARE(loadSpy.count(), 3); - QTRY_COMPARE(page.navigations.count(), 3); - QCOMPARE(page.navigations.at(0).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), - (int)QNetworkRequest::PreferNetwork); - QCOMPARE(page.navigations.at(1).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), - (int)QNetworkRequest::PreferNetwork); - QCOMPARE(page.navigations.at(2).request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(), - (int)QNetworkRequest::PreferCache); -#endif -} - -void tst_QWebEnginePage::loadCachedPage() -{ -#if !defined(QWEBENGINESETTINGS) - QSKIP("QWEBENGINESETTINGS"); -#else - TestPage page; - QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); - page.settings()->setMaximumPagesInCache(3); - - page.load(QUrl("data:text/html,This is first page")); - - QTRY_COMPARE(loadSpy.count(), 1); - QTRY_COMPARE(page.navigations.count(), 1); - - QUrl firstPageUrl = page.url(); - page.load(QUrl("data:text/html,This is second page")); - - QTRY_COMPARE(loadSpy.count(), 2); - QTRY_COMPARE(page.navigations.count(), 2); - - page.triggerAction(QWebEnginePage::Stop); - QVERIFY(page.history()->canGoBack()); - - QSignalSpy urlSpy(&page, SIGNAL(urlChanged(QUrl))); - QVERIFY(urlSpy.isValid()); - - page.triggerAction(QWebEnginePage::Back); - ::waitForSignal(&page, SIGNAL(urlChanged(QUrl))); - QCOMPARE(urlSpy.size(), 1); - - QList<QVariant> arguments1 = urlSpy.takeFirst(); - QCOMPARE(arguments1.at(0).toUrl(), firstPageUrl); -#endif -} - void tst_QWebEnginePage::backActionUpdate() { QWebEngineView view; diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 3893397cd..83f65f9d0 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -50,6 +50,7 @@ private Q_SLOTS: void reusePage(); void microFocusCoordinates(); void focusInputTypes(); + void unhandledKeyEventPropagation(); void horizontalScrollbarTest(); void crashTests(); @@ -321,6 +322,49 @@ void tst_QWebEngineView::focusInputTypes() #endif } +class KeyEventRecordingWidget : public QWidget { +public: + QList<QKeyEvent> pressEvents; + QList<QKeyEvent> releaseEvents; + void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE { pressEvents << *e; } + void keyReleaseEvent(QKeyEvent *e) Q_DECL_OVERRIDE { releaseEvents << *e; } +}; + +void tst_QWebEngineView::unhandledKeyEventPropagation() +{ + KeyEventRecordingWidget parentWidget; + QWebEngineView webView(&parentWidget); + parentWidget.show(); + QTest::qWaitForWindowExposed(&webView); + + QSignalSpy loadSpy(&webView, SIGNAL(loadFinished(bool))); + webView.setHtml("<input type='text'/>"); + QTRY_COMPARE(loadSpy.count(), 1); + + evaluateJavaScriptSync(webView.page(), "document.body.firstChild.focus()"); + + QTest::sendKeyEvent(QTest::Press, parentWidget.windowHandle(), Qt::Key_A, 'a', Qt::NoModifier); + QTest::sendKeyEvent(QTest::Release, parentWidget.windowHandle(), Qt::Key_A, 'a', Qt::NoModifier); + QTest::sendKeyEvent(QTest::Press, parentWidget.windowHandle(), Qt::Key_Left, QString(), Qt::NoModifier); + QTest::sendKeyEvent(QTest::Release, parentWidget.windowHandle(), Qt::Key_Left, QString(), Qt::NoModifier); + QTest::sendKeyEvent(QTest::Press, parentWidget.windowHandle(), Qt::Key_Left, QString(), Qt::NoModifier); + QTest::sendKeyEvent(QTest::Release, parentWidget.windowHandle(), Qt::Key_Left, QString(), Qt::NoModifier); + + // All this happens asychronously, wait for the last release event to know when we're done. + for (int i = 0; i < 20 && parentWidget.releaseEvents.size() < 3; ++i) + QTest::qWait(100); + + // The page will consume the 'a' and the first left key presses, the second left won't be + // used since the cursor will already be at the left end of the text input. + // Key releases will all come back unconsumed. + QCOMPARE(parentWidget.pressEvents.size(), 1); + QCOMPARE(parentWidget.pressEvents[0].key(), (int)Qt::Key_Left); + QCOMPARE(parentWidget.releaseEvents.size(), 3); + QCOMPARE(parentWidget.releaseEvents[0].key(), (int)Qt::Key_A); + QCOMPARE(parentWidget.releaseEvents[1].key(), (int)Qt::Key_Left); + QCOMPARE(parentWidget.releaseEvents[2].key(), (int)Qt::Key_Left); +} + void tst_QWebEngineView::horizontalScrollbarTest() { #if !defined(QWEBENGINEPAGE_SCROLL) diff --git a/tests/quicktestbrowser/ApplicationRoot.qml b/tests/quicktestbrowser/ApplicationRoot.qml new file mode 100644 index 000000000..56196efdc --- /dev/null +++ b/tests/quicktestbrowser/ApplicationRoot.qml @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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.1 + +QtObject { + id: root + property Component browserWindowComponent: BrowserWindow { + applicationRoot: root + onClosing: destroy() + } + property Component browserDialogComponent: BrowserDialog { + onClosing: destroy() + } + function createWindow() { return browserWindowComponent.createObject(root) } + function createDialog() { return browserDialogComponent.createObject(root) } + function load(url) { + var browserWindow = createWindow() + browserWindow.currentWebView.url = url + } +} diff --git a/tests/quicktestbrowser/BrowserDialog.qml b/tests/quicktestbrowser/BrowserDialog.qml new file mode 100644 index 000000000..038a62f28 --- /dev/null +++ b/tests/quicktestbrowser/BrowserDialog.qml @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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.1 +import QtQuick.Window 2.2 +import QtWebEngine 1.0 + +Window { + property alias currentWebView: webView + flags: Qt.Dialog + width: 800 + height: 600 + visible: true + onClosing: destroy() + WebEngineView { + id: webView + anchors.fill: parent + } +} diff --git a/tests/quicktestbrowser/quickwindow.qml b/tests/quicktestbrowser/BrowserWindow.qml index 6a5ef3187..d438075d8 100644 --- a/tests/quicktestbrowser/quickwindow.qml +++ b/tests/quicktestbrowser/BrowserWindow.qml @@ -39,7 +39,7 @@ ****************************************************************************/ import QtQuick 2.1 -import QtWebEngine 1.0 +import QtWebEngine 1.1 import QtWebEngine.experimental 1.0 import QtQuick.Controls 1.0 @@ -48,11 +48,11 @@ import QtQuick.Layouts 1.0 import QtQuick.Window 2.1 import QtQuick.Controls.Private 1.0 import Qt.labs.settings 1.0 - +import QtQuick.Dialogs 1.2 ApplicationWindow { id: browserWindow - function load(url) { currentWebView.url = url } + property QtObject applicationRoot property Item currentWebView: tabs.currentIndex < tabs.count ? tabs.getTab(tabs.currentIndex).item.webView : null property bool isFullScreen: visibility == Window.FullScreen @@ -73,6 +73,22 @@ ApplicationWindow { property alias errorPageEnabled: errorPageEnabled.checked; } + WebEngineProfile { + id: testProfile + storageName: "Test" + httpCacheType: httpDiskCacheEnabled.checked ? WebEngineProfile.DiskHttpCache : WebEngineProfile.MemoryHttpCache; + onDownloadRequested: { + downloadView.visible = true + downloadView.append(download) + download.accept() + } + } + + WebEngineProfile { + id: otrProfile + offTheRecord: true + } + // Make sure the Qt.WindowFullscreenButtonHint is set on Mac. Component.onCompleted: flags = flags | Qt.WindowFullscreenButtonHint @@ -81,6 +97,12 @@ ApplicationWindow { StyleItem { id: styleItem } property bool platformIsMac: styleItem.style == "mac" + Action { + shortcut: "Ctrl+D" + onTriggered: { + downloadView.visible = !downloadView.visible + } + } Action { id: focus @@ -122,6 +144,18 @@ ApplicationWindow { browserWindow.showNormal() } } + Action { + shortcut: "Ctrl+0" + onTriggered: zoomController.reset() + } + Action { + shortcut: "Ctrl+-" + onTriggered: zoomController.zoomOut() + } + Action { + shortcut: "Ctrl+=" + onTriggered: zoomController.zoomIn() + } Menu { id: backHistoryMenu @@ -223,6 +257,18 @@ ApplicationWindow { checked: WebEngine.settings.errorPageEnabled onCheckedChanged: WebEngine.settings.errorPageEnabled = checked } + MenuItem { + id: offTheRecordEnabled + text: "Off The Record" + checkable: true + checked: false + } + MenuItem { + id: httpDiskCacheEnabled + text: "HTTP Disk Cache" + checkable: true + checked: (testProfile.httpCacheType == WebEngineProfile.DiskHttpCache) + } } } } @@ -260,20 +306,6 @@ ApplicationWindow { Component.onCompleted: createEmptyTab() Component { - id: dialogComponent - Window { - property Item webView: _webView - width: 800 - height: 600 - visible: true - WebEngineView { - id: _webView - anchors.fill: parent - } - } - } - - Component { id: tabComponent Item { property alias webView: webEngineView @@ -300,6 +332,7 @@ ApplicationWindow { WebEngineView { id: webEngineView + profile: offTheRecordEnabled.checked ? otrProfile : testProfile anchors { fill: parent @@ -323,6 +356,28 @@ ApplicationWindow { } ] + onCertificateError: { + sslDialog.certError = error + sslDialog.text = "Certificate Error: " + error.description + sslDialog.visible = true + error.defer() + } + + onNewViewRequested: { + if (!request.userInitiated) + print("Warning: Blocked a popup window.") + else if (request.destination == WebEngineView.NewViewInTab) { + var tab = tabs.createEmptyTab() + request.openIn(tab.item.webView) + } else if (request.destination == WebEngineView.NewViewInDialog) { + var dialog = applicationRoot.createDialog() + request.openIn(dialog.currentWebView) + } else { + var window = applicationRoot.createWindow() + request.openIn(window.currentWebView) + } + } + experimental { isFullScreen: webEngineView.state == "FullScreen" && browserWindow.isFullScreen onFullScreenRequested: { @@ -335,21 +390,6 @@ ApplicationWindow { } } - onNewViewRequested: { - if (!request.userInitiated) - print("Warning: Blocked a popup window.") - else if (request.destination == WebEngineView.NewViewInTab) { - var tab = tabs.createEmptyTab() - request.openIn(tab.item.webView) - } else if (request.destination == WebEngineView.NewViewInDialog) { - var dialog = dialogComponent.createObject() - request.openIn(dialog.webView) - } else { - var component = Qt.createComponent("quickwindow.qml") - var window = component.createObject() - request.openIn(window.currentWebView) - } - } onFeaturePermissionRequested: { permBar.securityOrigin = securityOrigin; permBar.requestedFeature = feature; @@ -399,4 +439,36 @@ ApplicationWindow { } } } + + MessageDialog { + id: sslDialog + + property var certError + + standardButtons: StandardButton.Cancel | StandardButton.Ok + visible: false + title: "Do you want to accept this certificate?" + + onAccepted: certError.ignoreCertificateError() + onRejected: certError.rejectCertificate() + } + + DownloadView { + id: downloadView + visible: false + anchors.fill: parent + } + + ZoomController { + id: zoomController + y: parent.mapFromItem(currentWebView, 0 , 0).y - 4 + anchors.right: parent.right + width: (parent.width > 800) ? parent.width * 0.25 : 220 + anchors.rightMargin: (parent.width > 400) ? 100 : 0 + } + Binding { + target: currentWebView + property: "zoomFactor" + value: zoomController.zoomFactor + } } diff --git a/tests/quicktestbrowser/ButtonWithMenu.qml b/tests/quicktestbrowser/ButtonWithMenu.qml index 8058b958a..10f5dbbc3 100644 --- a/tests/quicktestbrowser/ButtonWithMenu.qml +++ b/tests/quicktestbrowser/ButtonWithMenu.qml @@ -47,7 +47,7 @@ ToolButton { id: root property Menu longPressMenu function showMenu() { - longPressMenu.__popup(0, root.height, 0) + longPressMenu.__popup(Qt.rect(0, root.height, 0, 0), 0) } Binding { diff --git a/tests/quicktestbrowser/DownloadView.qml b/tests/quicktestbrowser/DownloadView.qml new file mode 100644 index 000000000..3367dfc71 --- /dev/null +++ b/tests/quicktestbrowser/DownloadView.qml @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Styles 1.0 +import QtWebEngine 1.0 +import QtWebEngine.experimental 1.0 +import QtQuick.Layouts 1.0 + +Rectangle { + id: downloadView + color: "lightgray" + + ListModel { + id: downloadModel + property var downloads: [] + } + + function append(download) { + downloadModel.append(download) + downloadModel.downloads.push(download) + } + + Component { + id: downloadItemDelegate + + Rectangle { + width: listView.width + height: childrenRect.height + anchors.margins: 10 + radius: 3 + color: "transparent" + border.color: "black" + Rectangle { + id: progressBar + + property real progress: downloadModel.downloads[index] + ? downloadModel.downloads[index].receivedBytes / downloadModel.downloads[index].totalBytes : 0 + + radius: 3 + color: width == listView.width ? "green" : "#2b74c7" + width: listView.width * progress + height: cancelButton.height + + Behavior on width { + SmoothedAnimation { duration: 100 } + } + } + Rectangle { + anchors { + left: parent.left + right: parent.right + leftMargin: 20 + } + Label { + id: label + text: path + anchors { + verticalCenter: cancelButton.verticalCenter + left: parent.left + right: cancelButton.left + } + } + Button { + id: cancelButton + anchors.right: parent.right + iconSource: "icons/process-stop.png" + onClicked: { + var download = downloadModel.downloads[index] + + download.cancel() + + downloadModel.downloads = downloadModel.downloads.filter(function (el) { + return el.id !== download.id; + }); + downloadModel.remove(index) + } + } + } + } + + } + ListView { + id: listView + anchors { + topMargin: 10 + top: parent.top + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + width: parent.width - 20 + spacing: 5 + + model: downloadModel + delegate: downloadItemDelegate + + Text { + visible: !listView.count + horizontalAlignment: Text.AlignHCenter + height: 30 + anchors { + top: parent.top + left: parent.left + right: parent.right + } + font.pixelSize: 20 + text: "No active downloads." + } + + Rectangle { + color: "gray" + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + height: 30 + Button { + id: okButton + text: "OK" + anchors.centerIn: parent + onClicked: { + downloadView.visible = false + } + } + } + } +} diff --git a/tests/quicktestbrowser/FeaturePermissionBar.qml b/tests/quicktestbrowser/FeaturePermissionBar.qml index dd2e0f714..68ad43195 100644 --- a/tests/quicktestbrowser/FeaturePermissionBar.qml +++ b/tests/quicktestbrowser/FeaturePermissionBar.qml @@ -69,12 +69,14 @@ Rectangle { Layout.fillWidth: true function textForFeature(feature) { - if (feature === WebEngineViewExperimental.MediaAudioDevices) + if (feature === WebEngineViewExperimental.MediaAudioCapture) return "your microphone" - if (feature === WebEngineViewExperimental.MediaVideoDevices) + if (feature === WebEngineViewExperimental.MediaVideoCapture) return "your camera" - if (feature === WebEngineViewExperimental.MediaAudioVideoDevices) + if (feature === WebEngineViewExperimental.MediaAudioVideoCapture) return "your camera and microphone" + if (feature === WebEngineViewExperimental.Geolocation) + return "your position" } } diff --git a/tests/quicktestbrowser/ZoomController.qml b/tests/quicktestbrowser/ZoomController.qml new file mode 100644 index 000000000..a714ed2a9 --- /dev/null +++ b/tests/quicktestbrowser/ZoomController.qml @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia Plc and its Subsidiary(-ies) 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.3 +import QtQuick.Controls 1.2 +import QtQuick.Layouts 1.1 + +Rectangle { + property alias zoomFactor: slider.value ; + function zoomIn() { + visible = true + visibilityTimer.restart() + zoomFactor = zoomFactor + 0.25; + } + function zoomOut() { + visible = true + visibilityTimer.restart() + zoomFactor = zoomFactor - 0.25; + } + function reset() { zoomFactor = 1.0 } + + width: 220 + height: 30 + color: palette.window + visible: false + radius: 4 + + SystemPalette { + id: palette + } + Timer { + id: visibilityTimer + interval: 3000 + repeat: false + onTriggered: zoomController.visible = false + } + + RowLayout { + anchors.margins: 4 + anchors.fill: parent + ToolButton { + id: plusButton + text: '+' + onClicked: zoomIn() + } + ToolButton { + text: '\u2014' + id: minusButton + onClicked: zoomOut() + } + Slider { + id: slider + maximumValue: 5.0 + minimumValue: 0.25 + Layout.fillWidth: true; + stepSize: 0.05 + value: 1 + onValueChanged: visibilityTimer.restart() + } + Button { + text: "Reset" + onClicked: reset() + } + } +} diff --git a/tests/quicktestbrowser/main.cpp b/tests/quicktestbrowser/main.cpp index d8fe01aa1..2d5271176 100644 --- a/tests/quicktestbrowser/main.cpp +++ b/tests/quicktestbrowser/main.cpp @@ -39,7 +39,8 @@ ** ****************************************************************************/ -#include "quickwindow.h" +#include "utils.h" + #ifndef QT_NO_WIDGETS #include <QtWidgets/QApplication> typedef QApplication Application; @@ -47,15 +48,39 @@ typedef QApplication Application; #include <QtGui/QGuiApplication> typedef QGuiApplication Application; #endif -#include <qtwebengineglobal.h> +#include <QtQml/QQmlApplicationEngine> +#include <QtQml/QQmlContext> +#include <QtWebEngine/qtwebengineglobal.h> + +static QUrl startupUrl() +{ + QUrl ret; + QStringList args(qApp->arguments()); + args.takeFirst(); + Q_FOREACH (const QString& arg, args) { + if (arg.startsWith(QLatin1Char('-'))) + continue; + ret = Utils::fromUserInput(arg); + if (ret.isValid()) + return ret; + } + return QUrl(QStringLiteral("http://qt.io/")); +} int main(int argc, char **argv) { Application app(argc, argv); + // Enable dev tools by default for the test browser + if (qgetenv("QTWEBENGINE_REMOTE_DEBUGGING").isNull()) + qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "1337"); QtWebEngine::initialize(); - ApplicationEngine appEngine; + QQmlApplicationEngine appEngine; + Utils utils; + appEngine.rootContext()->setContextProperty("utils", &utils); + appEngine.load(QUrl("qrc:/ApplicationRoot.qml")); + QMetaObject::invokeMethod(appEngine.rootObjects().first(), "load", Q_ARG(QVariant, startupUrl())); return app.exec(); } diff --git a/tests/quicktestbrowser/quicktestbrowser.pro b/tests/quicktestbrowser/quicktestbrowser.pro index ac8fe74b3..b285c5e62 100644 --- a/tests/quicktestbrowser/quicktestbrowser.pro +++ b/tests/quicktestbrowser/quicktestbrowser.pro @@ -1,17 +1,20 @@ +requires(contains(QT_CONFIG, accessibility)) + TEMPLATE = app TARGET = quicktestbrowser macx: CONFIG -= app_bundle -HEADERS = quickwindow.h \ - util.h -SOURCES = quickwindow.cpp \ - main.cpp +HEADERS = utils.h +SOURCES = main.cpp -OTHER_FILES += ButtonWithMenu.qml \ +OTHER_FILES += ApplicationRoot.qml \ + BrowserDialog.qml \ + BrowserWindow.qml \ + ButtonWithMenu.qml \ ContextMenuExtras.qml \ - FeaturePermissionBar.qml \ - quickwindow.qml + DownloadView.qml \ + FeaturePermissionBar.qml RESOURCES += resources.qrc diff --git a/tests/quicktestbrowser/resources.qrc b/tests/quicktestbrowser/resources.qrc index cdc3d2304..80f1d1543 100644 --- a/tests/quicktestbrowser/resources.qrc +++ b/tests/quicktestbrowser/resources.qrc @@ -1,9 +1,13 @@ <!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/"> - <file>quickwindow.qml</file> + <file>ApplicationRoot.qml</file> + <file>BrowserDialog.qml</file> + <file>BrowserWindow.qml</file> <file>ContextMenuExtras.qml</file> <file>FeaturePermissionBar.qml</file> <file>ButtonWithMenu.qml</file> + <file>DownloadView.qml</file> + <file>ZoomController.qml</file> </qresource> <qresource prefix="icons"> <!-- To the risk of this breaking more often, do not duplicate the resources since this application won't be deployed --> diff --git a/tests/quicktestbrowser/quickwindow.h b/tests/quicktestbrowser/utils.h index ed25a23b8..3cb3fec5d 100644 --- a/tests/quicktestbrowser/quickwindow.h +++ b/tests/quicktestbrowser/utils.h @@ -38,18 +38,24 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#ifndef UTILS_H +#define UTILS_H -#ifndef QUICKWINDOW_H -#define QUICKWINDOW_H +#include <QtCore/QFileInfo> +#include <QtCore/QUrl> -#include <QQmlApplicationEngine> - -class QWebEngineView; - -class ApplicationEngine : public QQmlApplicationEngine { +class Utils : public QObject { Q_OBJECT public: - ApplicationEngine(); + Q_INVOKABLE static QUrl fromUserInput(const QString& userInput); }; -#endif // QUICKWINDOW_H +inline QUrl Utils::fromUserInput(const QString& userInput) +{ + QFileInfo fileInfo(userInput); + if (fileInfo.exists()) + return QUrl::fromLocalFile(fileInfo.absoluteFilePath()); + return QUrl::fromUserInput(userInput); +} + +#endif // UTILS_H diff --git a/tests/tests.pro b/tests/tests.pro index f6dec7a55..2922e5076 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -1,5 +1,3 @@ TEMPLATE = subdirs -isPlatformSupported() { - SUBDIRS += auto quicktestbrowser -} +SUBDIRS += auto quicktestbrowser |