summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--.qmake.conf5
-rw-r--r--configure.json34
-rw-r--r--examples/examples.pro9
-rw-r--r--examples/webengine/customdialogs/MessageRectangle.qml55
-rw-r--r--examples/webengine/customdialogs/SwitchButton.qml60
-rw-r--r--examples/webengine/customdialogs/WebView.qml125
-rw-r--r--examples/webengine/customdialogs/customdialogs.pro18
-rw-r--r--examples/webengine/customdialogs/customdialogs.qrc24
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-auth1.pngbin0 -> 6453 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-auth2.pngbin0 -> 7983 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-color1.pngbin0 -> 20401 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-color2.pngbin0 -> 6609 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-file1.pngbin0 -> 15736 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-file2.pngbin0 -> 9036 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-menu.pngbin0 -> 5484 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-prompt1.pngbin0 -> 5509 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-prompt2.pngbin0 -> 7839 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-validation1.pngbin0 -> 12523 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs-validation2.pngbin0 -> 12171 bytes
-rw-r--r--examples/webengine/customdialogs/doc/images/customdialogs.pngbin0 -> 11764 bytes
-rw-r--r--examples/webengine/customdialogs/doc/src/customdialogs.qdoc337
-rw-r--r--examples/webengine/customdialogs/forms/Authentication.qml68
-rw-r--r--examples/webengine/customdialogs/forms/AuthenticationForm.ui.qml161
-rw-r--r--examples/webengine/customdialogs/forms/Button.qml98
-rw-r--r--examples/webengine/customdialogs/forms/ColorCell.qml53
-rw-r--r--examples/webengine/customdialogs/forms/ColorPicker.qml68
-rw-r--r--examples/webengine/customdialogs/forms/ColorPickerForm.ui.qml225
-rw-r--r--examples/webengine/customdialogs/forms/FilePicker.qml81
-rw-r--r--examples/webengine/customdialogs/forms/FilePickerForm.ui.qml167
-rw-r--r--examples/webengine/customdialogs/forms/FileRow.qml82
-rw-r--r--examples/webengine/customdialogs/forms/JavaScript.qml81
-rw-r--r--examples/webengine/customdialogs/forms/JavaScriptForm.ui.qml149
-rw-r--r--examples/webengine/customdialogs/forms/Menu.qml59
-rw-r--r--examples/webengine/customdialogs/forms/MenuForm.ui.qml103
-rw-r--r--examples/webengine/customdialogs/icon.svg24
-rw-r--r--examples/webengine/customdialogs/index.html53
-rw-r--r--examples/webengine/customdialogs/main.cpp75
-rw-r--r--examples/webengine/customdialogs/main.qml90
-rw-r--r--examples/webengine/customdialogs/server.cpp75
-rw-r--r--examples/webengine/customdialogs/server.h65
-rw-r--r--examples/webengine/customdialogs/style.css37
-rw-r--r--examples/webenginewidgets/demobrowser/browsermainwindow.cpp2
-rw-r--r--examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc21
-rw-r--r--examples/webenginewidgets/spellchecker/spellchecker.pro22
-rw-r--r--examples/webenginewidgets/spellchecker/webview.cpp6
-rw-r--r--qtwebengine.pro13
m---------src/3rdparty0
-rw-r--r--src/core/api/core_api.pro4
-rw-r--r--src/core/browser_context_adapter.cpp10
-rw-r--r--src/core/browser_context_adapter.h5
-rw-r--r--src/core/browser_context_qt.cpp25
-rw-r--r--src/core/browser_context_qt.h6
-rw-r--r--src/core/chrome_qt.gyp4
-rw-r--r--src/core/config/common.pri5
-rw-r--r--src/core/config/desktop_linux.pri6
-rw-r--r--src/core/config/linux.pri2
-rw-r--r--src/core/content_browser_client_qt.cpp24
-rw-r--r--src/core/content_browser_client_qt.h4
-rw-r--r--src/core/content_client_qt.cpp3
-rw-r--r--src/core/delegated_frame_node.cpp6
-rw-r--r--src/core/doc/src/qtwebenginecore-index.qdoc1
-rw-r--r--src/core/doc/src/qtwebenginecore-module.qdoc1
-rw-r--r--src/core/gl_context_qt.cpp2
-rw-r--r--src/core/gl_surface_qt.cpp55
-rw-r--r--src/core/gyp_run.pro16
-rw-r--r--src/core/media_capture_devices_dispatcher.cpp1
-rw-r--r--src/core/pdfium_printing_wrapper_qt.cpp4
-rw-r--r--src/core/print_view_manager_qt.cpp20
-rw-r--r--src/core/proxy_config_service_qt.cpp5
-rw-r--r--src/core/qrc_protocol_handler_qt.cpp2
-rw-r--r--src/core/qrc_protocol_handler_qt.h2
-rw-r--r--src/core/renderer/content_renderer_client_qt.cpp12
-rw-r--r--src/core/renderer/render_frame_observer_qt.cpp12
-rw-r--r--src/core/renderer/render_frame_observer_qt.h11
-rw-r--r--src/core/renderer/web_channel_ipc_transport.cpp12
-rw-r--r--src/core/url_request_context_getter_qt.cpp2
-rw-r--r--src/core/web_contents_adapter.cpp51
-rw-r--r--src/core/web_contents_adapter_p.h2
-rw-r--r--src/core/web_contents_delegate_qt.cpp13
-rw-r--r--src/core/web_engine_context.cpp19
-rw-r--r--src/core/web_engine_library_info.cpp70
-rw-r--r--src/src.pro3
-rw-r--r--src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro5
-rw-r--r--src/webengine/api/qquickwebenginedialogrequests.cpp12
-rw-r--r--src/webengine/api/qquickwebenginedialogrequests_p.h6
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp58
-rw-r--r--src/webengine/api/qquickwebengineprofile.h8
-rw-r--r--src/webengine/api/qquickwebengineview.cpp6
-rw-r--r--src/webengine/doc/qtwebengine.qdocconf6
-rw-r--r--src/webengine/doc/snippets/qtwebengine_build_snippet.qdoc8
-rw-r--r--src/webengine/doc/src/qtwebengine-deploying.qdoc10
-rw-r--r--src/webengine/doc/src/qtwebengine-features.qdoc7
-rw-r--r--src/webengine/doc/src/qtwebengine-index.qdoc1
-rw-r--r--src/webengine/doc/src/qtwebengine-module.qdoc44
-rw-r--r--src/webengine/doc/src/qtwebengine-overview.qdoc10
-rw-r--r--src/webengine/doc/src/qtwebengine-platform-notes.qdoc24
-rw-r--r--src/webengine/doc/src/qwebengine-licensing.qdoc2
-rw-r--r--src/webengine/plugin/plugin.cpp28
-rw-r--r--src/webengine/plugin/plugins.qmltypes10
-rw-r--r--src/webengine/ui_delegates_manager.cpp3
-rw-r--r--src/webengine/webengine.pro2
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp5
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp46
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.h4
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp12
-rw-r--r--src/webenginewidgets/api/qwebengineview_p.h1
-rw-r--r--src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc (renamed from src/webenginewidgets/doc/snippets/qtwebengine_build_snippet.qdoc)0
-rw-r--r--src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc1
-rw-r--r--src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc4
-rw-r--r--src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc4
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp13
-rw-r--r--src/webenginewidgets/webenginewidgets.pro4
-rw-r--r--sync.profile17
-rw-r--r--tests/auto/quick/qmltests/BLACKLIST18
-rw-r--r--tests/auto/quick/qmltests/data/TestWebEngineView.qml22
-rw-r--r--tests/auto/quick/qmltests/data/favicon-candidates-gray.html10
-rw-r--r--tests/auto/quick/qmltests/data/favicon-multi-gray.html10
-rw-r--r--tests/auto/quick/qmltests/data/keyboardEvents.html98
-rw-r--r--tests/auto/quick/qmltests/data/redirect.html3
-rw-r--r--tests/auto/quick/qmltests/data/tst_findText.qml19
-rw-r--r--tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml13
-rw-r--r--tests/auto/quick/qmltests/data/tst_keyboardEvents.qml156
-rw-r--r--tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml42
-rw-r--r--tests/auto/quick/qmltests/data/tst_loadUrl.qml329
-rw-r--r--tests/auto/quick/qmltests/data/tst_navigationRequested.qml3
-rw-r--r--tests/auto/quick/qmltests/data/tst_newViewRequest.qml137
-rw-r--r--tests/auto/quick/qmltests/data/tst_settings.qml16
-rw-r--r--tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml8
-rw-r--r--tests/auto/quick/qmltests/data/tst_viewSource.qml12
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro4
-rw-r--r--tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp20
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp28
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/dict/de-DE.aff5
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/dict/de-DE.dic14
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro6
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp35
-rw-r--r--tests/auto/widgets/qwebengineview/resources/keyboardEvents.html98
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp90
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.qrc1
-rw-r--r--tests/auto/widgets/widgets.pro9
-rw-r--r--tests/manual/manual.pro3
-rw-r--r--tests/manual/quick/faviconbrowser/AddressBar.qml124
-rw-r--r--tests/manual/quick/faviconbrowser/FaviconPanel.qml256
-rw-r--r--tests/manual/quick/faviconbrowser/faviconbrowser.pro23
-rw-r--r--tests/manual/quick/faviconbrowser/faviconbrowser.qrc17
-rw-r--r--tests/manual/quick/faviconbrowser/main.cpp76
-rw-r--r--tests/manual/quick/faviconbrowser/main.qml192
-rw-r--r--tests/manual/quick/faviconbrowser/utils.h70
-rw-r--r--tests/manual/quick/quick.pro4
-rw-r--r--tools/about_credits_entry.tmpl2
-rw-r--r--tools/qmake/mkspecs/features/configure.prf105
-rw-r--r--tools/qmake/mkspecs/features/default_post.prf11
-rw-r--r--tools/qmake/mkspecs/features/default_pre.prf14
-rw-r--r--tools/qmake/mkspecs/features/functions.prf142
-rwxr-xr-xtools/scripts/take_snapshot.py6
156 files changed, 4997 insertions, 584 deletions
diff --git a/.gitignore b/.gitignore
index 21aab71d2..71d4cbb0e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,7 @@ moc_*.cpp
*.pyc
.pch
.obj
+
+# Compiled QML/JS code
+*.qmlc
+*.jsc
diff --git a/.qmake.conf b/.qmake.conf
index f0afa8682..a988f0fac 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,4 +1,9 @@
QMAKEPATH += $$PWD/tools/qmake
+
+# Resolve root directories for sources
+QTWEBENGINE_ROOT = $$PWD
+QTWEBENGINE_OUT_ROOT = $$shadowed($$PWD)
+
load(qt_build_config)
CONFIG += warning_clean
diff --git a/configure.json b/configure.json
new file mode 100644
index 000000000..63abd1dba
--- /dev/null
+++ b/configure.json
@@ -0,0 +1,34 @@
+{
+ "module": "webengine",
+
+ "commandline": {
+ "options": {
+ "proprietary-codecs": "boolean",
+ "spellchecker": "boolean"
+ }
+ },
+
+ "features": {
+ "proprietary-codecs": {
+ "label": "Proprietary Codecs",
+ "autoDetect": false,
+ "purpose": "Enables the use of proprietary codecs such as h.264/h.265 and MP3",
+ "output": [ "privateFeature" ]
+ },
+ "spellchecker": {
+ "label": "Spellchecker",
+ "purpose": "Enables the use of Chromium's spellchecker",
+ "output": [ "privateFeature" ]
+ }
+ },
+
+ "summary": [
+ {
+ "section": "Qt WebEngine",
+ "entries": [
+ "proprietary-codecs",
+ "spellchecker"
+ ]
+ }
+ ]
+}
diff --git a/examples/examples.pro b/examples/examples.pro
index f15007e83..1a0f3a263 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -2,6 +2,7 @@ TEMPLATE=subdirs
qtHaveModule(webengine) {
SUBDIRS += \
+ webengine/customdialogs \
webengine/minimal \
webengine/quicknanobrowser
}
@@ -15,8 +16,12 @@ qtHaveModule(webenginewidgets) {
webenginewidgets/markdowneditor \
webenginewidgets/simplebrowser
- !contains(WEBENGINE_CONFIG, no_spellcheck):!osx:!cross_compile {
- SUBDIRS += webenginewidgets/spellchecker
+ contains(WEBENGINE_CONFIG, use_spellchecker):!cross_compile {
+ !contains(WEBENGINE_CONFIG, use_native_spellchecker) {
+ SUBDIRS += webenginewidgets/spellchecker
+ } else {
+ message("Spellcheck example will not be built because it depends on usage of Hunspell dictionaries.")
+ }
}
}
diff --git a/examples/webengine/customdialogs/MessageRectangle.qml b/examples/webengine/customdialogs/MessageRectangle.qml
new file mode 100644
index 000000000..e0ace7ca5
--- /dev/null
+++ b/examples/webengine/customdialogs/MessageRectangle.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.0
+
+Rectangle {
+ property alias text: messageText.text
+ width: parent.width
+ height: 30
+ visible: false
+ color: "#80c342"
+ Text {
+ id: messageText
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ font.pointSize: 12
+ }
+}
diff --git a/examples/webengine/customdialogs/SwitchButton.qml b/examples/webengine/customdialogs/SwitchButton.qml
new file mode 100644
index 000000000..75a2c6452
--- /dev/null
+++ b/examples/webengine/customdialogs/SwitchButton.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.0
+import QtQuick.Controls 1.4 as Controls
+import QtQuick.Layouts 1.3
+
+Item {
+ width: parent.width
+ height: 40
+ property alias checked: switcher.checked
+ RowLayout {
+ anchors.centerIn: parent
+ Text {
+ text: qsTr("Use default dialogs")
+ font.pointSize: 12
+ }
+ Controls.Switch {
+ id: switcher
+ checked: true
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/WebView.qml b/examples/webengine/customdialogs/WebView.qml
new file mode 100644
index 000000000..591789caa
--- /dev/null
+++ b/examples/webengine/customdialogs/WebView.qml
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.0
+import QtWebEngine 1.4
+
+WebEngineView {
+
+ url: "qrc:/index.html"
+ property bool useDefaultDialogs: true
+ signal openForm(var form)
+
+ onContextMenuRequested: function(request) {
+ // we only show menu for links with #openMenu
+ if (!request.linkUrl.toString().endsWith("#openMenu")) {
+ request.accepted = true;
+ return;
+ }
+ // return early to show default menu
+ if (useDefaultDialogs)
+ return;
+
+ request.accepted = true;
+ openForm({item: Qt.resolvedUrl("forms/Menu.qml"),
+ properties: {"request": request}});
+ }
+
+ onAuthenticationDialogRequested: function(request) {
+ if (useDefaultDialogs)
+ return;
+
+ request.accepted = true;
+ openForm({item: Qt.resolvedUrl("forms/Authentication.qml"),
+ properties: {"request": request}});
+ }
+
+ onJavaScriptDialogRequested: function(request) {
+ if (useDefaultDialogs)
+ return;
+
+ request.accepted = true;
+ openForm({item: Qt.resolvedUrl("forms/JavaScript.qml"),
+ properties: {"request": request}});
+ }
+
+ onColorDialogRequested: function(request) {
+ if (useDefaultDialogs)
+ return;
+
+ request.accepted = true;
+ openForm({item: Qt.resolvedUrl("forms/ColorPicker.qml"),
+ properties: {"request": request}});
+ }
+
+ onFileDialogRequested: function(request) {
+ if (useDefaultDialogs)
+ return;
+
+ request.accepted = true;
+ openForm({item: Qt.resolvedUrl("forms/FilePicker.qml"),
+ properties: {"request": request}});
+
+ }
+
+ onFormValidationMessageRequested: function(request) {
+ switch (request.type) {
+ case FormValidationMessageRequest.Show:
+ if (useDefaultDialogs)
+ return;
+
+ request.accepted = true;
+ validationMessage.text = request.text;
+ validationMessage.y = request.anchor.y + request.anchor.height + 10;
+ validationMessage.visible = true;
+ break;
+ case FormValidationMessageRequest.Move:
+ break;
+ case FormValidationMessageRequest.Hide:
+ validationMessage.visible = false;
+ break;
+ }
+ }
+
+ MessageRectangle {
+ id: validationMessage
+ z: 1
+ }
+}
diff --git a/examples/webengine/customdialogs/customdialogs.pro b/examples/webengine/customdialogs/customdialogs.pro
new file mode 100644
index 000000000..5861f3af7
--- /dev/null
+++ b/examples/webengine/customdialogs/customdialogs.pro
@@ -0,0 +1,18 @@
+QT += webengine
+
+HEADERS += \
+ server.h
+
+SOURCES += \
+ main.cpp \
+ server.cpp
+
+RESOURCES += \
+ customdialogs.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/webengine/customdialogs
+INSTALLS += target
+
+qtHaveModule(widgets) {
+ QT += widgets # QApplication is required to get native styling with QtQuickControls
+}
diff --git a/examples/webengine/customdialogs/customdialogs.qrc b/examples/webengine/customdialogs/customdialogs.qrc
new file mode 100644
index 000000000..5ab5b11cd
--- /dev/null
+++ b/examples/webengine/customdialogs/customdialogs.qrc
@@ -0,0 +1,24 @@
+<RCC>
+ <qresource prefix="/">
+ <file>forms/AuthenticationForm.ui.qml</file>
+ <file>forms/Authentication.qml</file>
+ <file>forms/Button.qml</file>
+ <file>forms/ColorCell.qml</file>
+ <file>forms/ColorPickerForm.ui.qml</file>
+ <file>forms/ColorPicker.qml</file>
+ <file>forms/FilePickerForm.ui.qml</file>
+ <file>forms/FilePicker.qml</file>
+ <file>forms/FileRow.qml</file>
+ <file>forms/JavaScriptForm.ui.qml</file>
+ <file>forms/JavaScript.qml</file>
+ <file>forms/MenuForm.ui.qml</file>
+ <file>forms/Menu.qml</file>
+ <file>icon.svg</file>
+ <file>index.html</file>
+ <file>main.qml</file>
+ <file>MessageRectangle.qml</file>
+ <file>style.css</file>
+ <file>SwitchButton.qml</file>
+ <file>WebView.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-auth1.png b/examples/webengine/customdialogs/doc/images/customdialogs-auth1.png
new file mode 100644
index 000000000..2bde8bd8e
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-auth1.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-auth2.png b/examples/webengine/customdialogs/doc/images/customdialogs-auth2.png
new file mode 100644
index 000000000..ce358fca0
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-auth2.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-color1.png b/examples/webengine/customdialogs/doc/images/customdialogs-color1.png
new file mode 100644
index 000000000..a51d1bdd3
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-color1.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-color2.png b/examples/webengine/customdialogs/doc/images/customdialogs-color2.png
new file mode 100644
index 000000000..3b0b2e986
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-color2.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-file1.png b/examples/webengine/customdialogs/doc/images/customdialogs-file1.png
new file mode 100644
index 000000000..0ff39bf38
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-file1.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-file2.png b/examples/webengine/customdialogs/doc/images/customdialogs-file2.png
new file mode 100644
index 000000000..e56078c44
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-file2.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-menu.png b/examples/webengine/customdialogs/doc/images/customdialogs-menu.png
new file mode 100644
index 000000000..3409c951c
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-menu.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-prompt1.png b/examples/webengine/customdialogs/doc/images/customdialogs-prompt1.png
new file mode 100644
index 000000000..988b4deea
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-prompt1.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-prompt2.png b/examples/webengine/customdialogs/doc/images/customdialogs-prompt2.png
new file mode 100644
index 000000000..085339378
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-prompt2.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-validation1.png b/examples/webengine/customdialogs/doc/images/customdialogs-validation1.png
new file mode 100644
index 000000000..38fa86235
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-validation1.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs-validation2.png b/examples/webengine/customdialogs/doc/images/customdialogs-validation2.png
new file mode 100644
index 000000000..247d2711b
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs-validation2.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/images/customdialogs.png b/examples/webengine/customdialogs/doc/images/customdialogs.png
new file mode 100644
index 000000000..13322d2f6
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/images/customdialogs.png
Binary files differ
diff --git a/examples/webengine/customdialogs/doc/src/customdialogs.qdoc b/examples/webengine/customdialogs/doc/src/customdialogs.qdoc
new file mode 100644
index 000000000..f5a18b591
--- /dev/null
+++ b/examples/webengine/customdialogs/doc/src/customdialogs.qdoc
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example webengine/customdialogs
+ \title WebEngine Qt Quick Custom Dialogs Example
+ \ingroup webengine-examples
+ \brief Customizes UI elements of Qt WebEngine's dialogs
+
+ \image customdialogs.png
+
+ A web page might request dialogs for various purposes, such as
+ authentication, picking colors, choosing files, and responding to JavaScript
+ alerts, confirmation requests, and prompts.
+
+ \e {Custom Dialogs} demonstrates how to use WebEngine dialog request objects
+ to implement custom dialogs for use instead of the default dialogs.
+
+ \include examples-run.qdocinc
+
+ \section1 UI Elements of WebEngineView
+
+ In this example, we create a simple \c index.html page that contains buttons
+ and text fields for triggering a context menu and the following dialogs:
+
+ \list
+ \li HTTP Authentication Dialog
+ \li Proxy Authentication Dialog
+ \li JavaScript Alert, Confirm, and Prompt Dialogs
+ \li Color Picker Dialog
+ \li File Picker Dialog
+ \li Form Validation Message
+ \endlist
+
+ \section1 Triggering Dialogs
+
+ The technical details on how the dialogs are triggered are beyond the scope
+ of this example. The only thing worth mentioning is that we fire up the
+ localhost TCP server when the example starts up. The server is needed to
+ get proxy and HTTP authentication requests.
+
+ \section1 Custom Dialogs
+
+ The custom dialogs are just \e {Qt Quick Designer UI Forms} without any
+ business logic. The point here is to present the glue code that is required
+ to display the custom dialog for a particular web engine dialog or a menu
+ request.
+
+ \section1 Creating the Main Window
+
+ In \c main.cpp, we initialize the WebEngine the same way as in the
+ \l {WebEngine Qt Quick Minimal Example}:
+
+ \quotefromfile webengine/customdialogs/main.cpp
+ \skipto main
+ \printuntil }
+
+ In addition, we set up a proxy and a TCP server to be able to simulate proxy
+ and HTTP authetication requests.
+
+ In \c main.qml, we create a top level window, which contains a StackView
+ with a SwitchButton and a WebView:
+
+ \quotefromfile webengine/customdialogs/main.qml
+ \skipto Window
+ \printuntil Component
+ \printuntil }
+ \printline }
+
+ \section1 Handling Web Engine Requests
+
+ In this example, we implement the handling of the following web engine
+ requests:
+
+ \list
+ \li ContextMenuRequest
+ \li AuthenticationDialogRequest
+ \li JavaScriptDialogRequest
+ \li ColorDialogRequest
+ \li FileDialogRequest
+ \li FormValidationMessageRequest
+ \endlist
+
+ \section2 Context Menu Requests
+
+ \l [QML]{ContextMenuRequest} is a request object that is passed as a
+ parameter of the WebEngineView::contextMenuRequested signal. We use the
+ \c onContextMenuRequested signal handler to handle requests for
+ \c #openMenu URL links:
+
+ \quotefromfile webengine/customdialogs/WebView.qml
+ \skipto WebEngineView
+ \printuntil {
+ \dots 4
+ \skipto onContextMenuRequested
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \dots 4
+ \skipuntil onFormValidationMessageRequested
+ \skipuntil }
+ \skipuntil }
+ \skipuntil }
+ \skipto }
+ \printline }
+
+ The first text field from the top on our page triggers the request. Next,
+ we check whether we should use the default menu. If not, we accept the
+ request and switch the view to show the \c MenuForm:
+
+ \image customdialogs-menu.png
+
+ \quotefromfile webengine/customdialogs/forms/Menu.qml
+ \skipto MenuForm
+ \printuntil }
+ \printuntil }
+
+ To keep things simple, we do not provide any logic on component completion,
+ and we simply close the form on any action.
+
+ \section2 Authentication Dialog Requests
+
+ \image customdialogs-auth1.png
+
+ \l [QML]{AuthenticationDialogRequest} is a request object that is passed
+ as a parameter of the WebEngineView::authenticationDialogRequested signal:
+
+ \quotefromfile webengine/customdialogs/WebView.qml
+ \skipto WebEngineView
+ \printuntil {
+ \dots 4
+ \skipto onAuthenticationDialogRequested
+ \printuntil }
+ \printuntil }
+ \dots 4
+ \skipuntil onFormValidationMessageRequested
+ \skipuntil }
+ \skipuntil }
+ \skipuntil }
+ \skipto }
+ \printline }
+
+ We use the \c onAuthenticationDialogRequested signal handler to check
+ whether we should use the default authentication dialog. If not, we accept
+ the request and switch the view to show the \c AuthenticationForm:
+
+ \image customdialogs-auth2.png
+
+ \quotefromfile webengine/customdialogs/forms/Authentication.qml
+ \skipto AuthenticationForm
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ On component completion, we log the request type. The user can fill in the
+ credentials and click \uicontrol Login. We provide \c onClicked handlers to
+ accept or reject the authentication dialog. The TCP server on localhost does
+ not handle real authentication, and therefore we call \c rejectDialog()
+ instead of \c acceptDialog() also for the login button \c clicked signal.
+
+ \section2 JavaScript Dialog Requests
+
+ \image customdialogs-prompt1.png
+
+ \l [QML]{JavaScriptDialogRequest} is a request object that is passed as a
+ parameter of the WebEngineView::javaScriptDialogRequested signal:
+
+ \quotefromfile webengine/customdialogs/WebView.qml
+ \skipto WebEngineView
+ \printuntil {
+ \dots 4
+ \skipto onJavaScriptDialogRequested
+ \printuntil }
+ \printuntil }
+ \dots 4
+ \skipuntil onFormValidationMessageRequested
+ \skipuntil }
+ \skipuntil }
+ \skipuntil }
+ \skipto }
+ \printline }
+
+ We use the \c onJavaScriptDialogRequested signal handler to check
+ whether we should use the default JavaScript dialog. If not, we accept the
+ request and switch the view to show the \c JavaScriptForm:
+
+ \image customdialogs-prompt2.png
+
+ \quotefromfile webengine/customdialogs/forms/JavaScript.qml
+ \skipto JavaScriptForm
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ On component completion, we customize the form based on the request type.
+ For a JavaScript prompt dialog we use \c dialogAccept() with the
+ \c prompt.text argument.
+
+ \section2 Color Dialog Requests
+
+ \image customdialogs-color1.png
+
+ \l [QML]{ColorDialogRequest} is a request object that is passed as a
+ parameter of the WebEngineView::colorDialogRequested signal:
+
+ \quotefromfile webengine/customdialogs/WebView.qml
+ \skipto WebEngineView
+ \printuntil {
+ \dots 4
+ \skipto onColorDialogRequested
+ \printuntil }
+ \printuntil }
+ \dots 4
+ \skipuntil onFormValidationMessageRequested
+ \skipuntil }
+ \skipuntil }
+ \skipuntil }
+ \skipto }
+ \printline }
+
+ We use the \c onColorDialogRequested signal handler to check whether
+ we should use the default color picker dialog. If not, we accept the request
+ and switch the view to show the \c ColorPickerForm:
+
+ \image customdialogs-color2.png
+
+ \quotefromfile webengine/customdialogs/forms/ColorPicker.qml
+ \skipto ColorPickerForm
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ On component completion, we create callbacks for all the color cells. When
+ the user selects the color and clicks \c OK, we pass the selected color to
+ the \c dialogAccept() method.
+
+ \section2 File Dialog Requests
+
+ \image customdialogs-file1.png
+
+ \l [QML]{FileDialogRequest} is a request object that is passed as a
+ parameter of the WebEngineView::fileDialogRequested signal:
+
+ \quotefromfile webengine/customdialogs/WebView.qml
+ \skipto WebEngineView
+ \printuntil {
+ \dots 4
+ \skipto onFileDialogRequested
+ \printuntil }
+ \printuntil }
+ \dots 4
+ \skipuntil onFormValidationMessageRequested
+ \skipuntil }
+ \skipuntil }
+ \skipuntil }
+ \skipto }
+ \printline }
+
+ We use the \c onFileDialogRequested signal handler to check whether
+ we should use the default color picker dialog. If not, we accept the request
+ and switch the view to show the \c FilePickerForm:
+
+ \image customdialogs-file2.png
+
+ \quotefromfile webengine/customdialogs/forms/FilePicker.qml
+ \skipto FilePickerForm
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \printuntil }
+
+ On component completion, we create callbacks for selecting files. When the user selects a
+ file and clicks \c OK, we pass the selected file to the \c dialogAccept
+ method.
+
+ \section2 Form Validation Message Requests
+
+ \image customdialogs-validation1.png
+
+ \l [QML]{FormValidationMessageRequest} is a request object that is passed as a
+ parameter of the WebEngineView::formValidationMessageRequested signal:
+
+ \quotefromfile webengine/customdialogs/WebView.qml
+ \skipto WebEngineView
+ \printuntil url
+ \dots 4
+ \skipto onFormValidationMessageRequested
+ \printuntil }
+ \printuntil }
+ \printuntil }
+ \skipto }
+ \printline }
+
+ We use the \c onFormValidationMessageRequested signal handler to check
+ whether we should use the default message bubble. If not, we accept the
+ request and customize \c validationMessage. Depending on the type of the
+ request, we show, move, or hide the message.
+
+ \image customdialogs-validation2.png
+*/
diff --git a/examples/webengine/customdialogs/forms/Authentication.qml b/examples/webengine/customdialogs/forms/Authentication.qml
new file mode 100644
index 000000000..8ee0a416f
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/Authentication.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+import QtWebEngine 1.4
+
+AuthenticationForm {
+ property QtObject request
+ signal closeForm()
+
+ cancelButton.onClicked: {
+ request.dialogReject();
+ closeForm();
+ }
+
+ loginButton.onClicked: {
+ request.dialogReject();
+ closeForm();
+ }
+
+ Component.onCompleted: {
+ switch (request.type) {
+ case AuthenticationDialogRequest.AuthenticationTypeHTTP:
+ console.log("HTTP Authentication Required. Host says: " + request.realm);
+ break;
+ case AuthenticationDialogRequest.AuthenticationTypeProxy:
+ console.log("Proxy Authentication Required for: " + request.proxyHost);
+ break;
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/AuthenticationForm.ui.qml b/examples/webengine/customdialogs/forms/AuthenticationForm.ui.qml
new file mode 100644
index 000000000..0ba27acdb
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/AuthenticationForm.ui.qml
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+import QtQuick.Layouts 1.3
+import QtQuick.Controls 1.0 as Controls
+
+Item {
+ id: item1
+ property alias cancelButton: cancelButton
+ property alias loginButton: loginButton
+ property alias userName: userName
+ property alias password: password
+
+ ColumnLayout {
+ id: columnLayout
+ anchors.topMargin: 20
+ anchors.top: parent.top
+ anchors.bottomMargin: 20
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: 20
+ anchors.right: parent.right
+ anchors.leftMargin: 20
+ anchors.left: parent.left
+
+ Image {
+ id: image
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ source: "qrc:/icon.svg"
+ }
+
+ Rectangle {
+ id: rectangle
+ height: 30
+ anchors.rightMargin: 0
+ anchors.leftMargin: 0
+ anchors.right: parent.right
+ anchors.left: parent.left
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ color: "#25a6e2"
+ }
+ GradientStop {
+ color: "#188bd0"
+ }
+ }
+
+ Text {
+ id: textArea
+ x: 54
+ y: 5
+ color: "#ffffff"
+ text: qsTr("Restricted Area")
+ font.pointSize: 12
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ Item {
+ width: 40
+ height: 40
+ }
+
+ Text {
+ id: userNameText
+ text: qsTr("Username:")
+ font.pointSize: 12
+ }
+
+ Controls.TextField {
+ id: userName
+ width: 300
+ height: 22
+ Layout.fillWidth: true
+ font.pointSize: 12
+ }
+
+ Text {
+ id: passwordText
+ text: qsTr("Password:")
+ font.pointSize: 12
+ }
+
+ Controls.TextField {
+ id: password
+ width: 300
+ height: 26
+ Layout.fillWidth: true
+ font.pointSize: 12
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+
+ RowLayout {
+ id: rowLayout
+ width: 100
+ height: 100
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Button {
+ id: cancelButton
+ width: 90
+ height: 30
+ btnText: qsTr("Cancel")
+ btnBlue: false
+ }
+
+ Button {
+ id: loginButton
+ width: 90
+ height: 30
+ btnText: qsTr("Login")
+ btnBlue: false
+ }
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/Button.qml b/examples/webengine/customdialogs/forms/Button.qml
new file mode 100644
index 000000000..8ae0865d1
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/Button.qml
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+
+Rectangle {
+ id: root
+ width: 200
+ height: 30
+ radius: 5
+ property string btnText: "Name"
+ property bool btnEnable: true
+ property bool btnBlue: true
+ opacity: btnEnable ? 1.0 : 0.5
+ signal clicked()
+ gradient: btnBlue ? blueButton : greenButton
+ Text {
+ id: textArea
+ x: 54
+ y: 5
+ color: "#ffffff"
+ text: parent.btnText
+ font.pointSize: 12
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ font.bold: false
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onClicked: {
+ if (btnEnable)
+ root.clicked();
+ }
+ }
+
+ Gradient {
+ id: blueButton
+ GradientStop {
+ position: 0
+ color: "#25a6e2"
+ }
+ GradientStop {
+ position: mouseArea.pressed && root.btnEnable ? 0.7 :1
+ color: "#188bd0"
+ }
+ }
+
+ Gradient {
+ id: greenButton
+ GradientStop {
+ position: 0
+ color: "#80c342"
+ }
+ GradientStop {
+ position: mouseArea.pressed && root.btnEnable ? 0.7 :1
+ color: "#5fac18"
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/ColorCell.qml b/examples/webengine/customdialogs/forms/ColorCell.qml
new file mode 100644
index 000000000..197cca3d3
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/ColorCell.qml
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+
+Rectangle {
+ id: rectangle
+ width: 50
+ height: 50
+ signal clicked()
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onClicked: rectangle.clicked(color)
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/ColorPicker.qml b/examples/webengine/customdialogs/forms/ColorPicker.qml
new file mode 100644
index 000000000..d4ab1abae
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/ColorPicker.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.[B"
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.4
+
+ColorPickerForm {
+ property QtObject request
+ signal closeForm()
+
+ okButton.onClicked: {
+ request.dialogAccept(colorPicker.color);
+ closeForm();
+ }
+
+ cancelButton.onClicked: {
+ request.dialogReject();
+ closeForm();
+ }
+
+ function createCallback(color) {
+ return function() { colorPicker.color = color };
+ }
+
+ Component.onCompleted:{
+ for (var i = 0; i < grid.children.length; i++) {
+ var cell = grid.children[i];
+ cell.clicked.connect(createCallback(cell.color));
+ }
+ colorPicker.color = request.color;
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/ColorPickerForm.ui.qml b/examples/webengine/customdialogs/forms/ColorPickerForm.ui.qml
new file mode 100644
index 000000000..d50f727f1
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/ColorPickerForm.ui.qml
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+import QtQuick.Layouts 1.3
+
+Item {
+ property alias cancelButton: cancelButton
+ property alias okButton: okButton
+ property string message: "Message"
+ property string title: "Title"
+ property alias blue1: blue1
+ property alias grid: grid
+ property alias colorPicker: colorPicker
+
+ ColumnLayout {
+ id: columnLayout
+ anchors.topMargin: 20
+ anchors.top: parent.top
+ anchors.bottomMargin: 20
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: 20
+ anchors.right: parent.right
+ anchors.leftMargin: 20
+ anchors.left: parent.left
+
+ Image {
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ source: "qrc:/icon.svg"
+ }
+
+ Rectangle {
+ height: 30
+ anchors.rightMargin: 0
+ anchors.leftMargin: 0
+ anchors.right: parent.right
+ anchors.left: parent.left
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ color: "#25a6e2"
+ }
+
+ GradientStop {
+ color: "#188bd0"
+ }
+ }
+
+ Text {
+ id: title
+ x: 54
+ y: 5
+ color: "#ffffff"
+ text: qsTr("Select Color")
+ font.pointSize: 12
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ Item {
+ width: 40
+ height: 40
+ }
+
+ GridLayout {
+ id: grid
+ columns: 5
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+
+ ColorCell {
+ id: blue1
+ color: "#26d5f8"
+ }
+ ColorCell {
+ id: green1
+ color: "#25f93d"
+ }
+ ColorCell {
+ id: red1
+ color: "#f71111"
+ }
+ ColorCell {
+ id: yellow1
+ color: "#faf23c"
+ }
+ ColorCell {
+ id: orange1
+ color: "#ec8505"
+ }
+ ColorCell {
+ id: blue2
+ color: "#037eaa"
+ }
+ ColorCell {
+ id: green2
+ color: "#389a13"
+ }
+ ColorCell {
+ id: red2
+ color: "#b2001b"
+ }
+ ColorCell {
+ id: yellow2
+ color: "#caca03"
+ }
+ ColorCell {
+ id: orange2
+ color: "#bb4900"
+ }
+ ColorCell {
+ id: blue3
+ color: "#01506c"
+ }
+ ColorCell {
+ id: green3
+ color: "#37592b"
+ }
+ ColorCell {
+ id: red3
+ color: "#700113"
+ }
+ ColorCell {
+ id: yellow3
+ color: "#848404"
+ }
+
+ ColorCell {
+ id: orange3
+ color: "#563100"
+ }
+ }
+
+ Item {
+ width: 10
+ height: 10
+ }
+
+ Rectangle {
+ width: 90
+ height: 90
+ color: "#000000"
+ radius: 4
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+
+ Rectangle {
+ id: colorPicker
+ height: 80
+ color: "#ffffff"
+ anchors.rightMargin: 5
+ anchors.leftMargin: 5
+ anchors.bottomMargin: 5
+ anchors.topMargin: 5
+ anchors.fill: parent
+ }
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+
+ RowLayout {
+ id: rowLayout
+ width: 100
+ height: 100
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Button {
+ id: cancelButton
+ width: 90
+ height: 30
+ btnText: qsTr("Cancel")
+ btnBlue: false
+ }
+
+ Button {
+ id: okButton
+ width: 90
+ height: 30
+ btnText: qsTr("OK")
+ btnBlue: false
+ }
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/FilePicker.qml b/examples/webengine/customdialogs/forms/FilePicker.qml
new file mode 100644
index 000000000..e459a5ceb
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/FilePicker.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+
+FilePickerForm {
+ property QtObject request
+ property string selectedFile
+ signal closeForm()
+
+ cancelButton.onClicked: {
+ request.dialogReject();
+ closeForm();
+ }
+
+ okButton.onClicked: {
+ request.dialogAccept('/' + selectedFile);
+ closeForm();
+ }
+
+ function createCallback(fileIndex) {
+ return function() {
+ for (var i = 0; i < files.children.length; i++) {
+ var file = files.children[i];
+ if (i === fileIndex) {
+ selectedFile = file.text;
+ file.selected = true;
+ } else {
+ file.selected = false;
+ }
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ selectedFile = request.defaultFileName;
+ for (var i = 0; i < files.children.length; i++) {
+ var file = files.children[i];
+ file.clicked.connect(createCallback(i));
+ if (file.text === selectedFile)
+ file.selected = true;
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/FilePickerForm.ui.qml b/examples/webengine/customdialogs/forms/FilePickerForm.ui.qml
new file mode 100644
index 000000000..67c9821b2
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/FilePickerForm.ui.qml
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+import QtQuick.Layouts 1.3
+
+Item {
+ property alias cancelButton: cancelButton
+ property alias okButton: okButton
+ property string message: "Message"
+ property string title: "Title"
+ property alias files: files
+
+ ColumnLayout {
+ id: columnLayout
+ anchors.topMargin: 20
+ anchors.top: parent.top
+ anchors.bottomMargin: 20
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: 20
+ anchors.right: parent.right
+ anchors.leftMargin: 20
+ anchors.left: parent.left
+
+ Image {
+ id: image
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ source: "qrc:/icon.svg"
+ }
+
+ Rectangle {
+ id: rectangle
+ height: 30
+ anchors.rightMargin: 0
+ anchors.leftMargin: 0
+ anchors.right: parent.right
+ anchors.left: parent.left
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ color: "#25a6e2"
+ }
+
+ GradientStop {
+ color: "#188bd0"
+ }
+ }
+
+ Text {
+ id: title
+ x: 54
+ y: 5
+ color: "#ffffff"
+ text: qsTr("Select File")
+ font.pointSize: 12
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ Item {
+ width: 40
+ height: 40
+ }
+
+ ColumnLayout {
+ id: files
+
+ FileRow {
+ id: filename1
+ text: "example.qdoc"
+ }
+
+ FileRow {
+ id: filename2
+ text: "factory.cpp"
+ }
+
+ FileRow {
+ id: filename3
+ text: "index.html"
+ }
+
+ FileRow {
+ id: filename4
+ text: "main.qml"
+ }
+
+ FileRow {
+ id: filename5
+ text: "qt-logo.png"
+ }
+
+ FileRow {
+ id: filename6
+ text: "window.h"
+ }
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+
+ RowLayout {
+ id: rowLayout
+ width: 20
+ height: 100
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Button {
+ id: cancelButton
+ width: 90
+ height: 30
+ btnText: qsTr("Cancel")
+ btnBlue: false
+ }
+
+ Button {
+ id: okButton
+ width: 90
+ height: 30
+ btnText: qsTr("OK")
+ btnBlue: false
+ }
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/FileRow.qml b/examples/webengine/customdialogs/forms/FileRow.qml
new file mode 100644
index 000000000..be0611323
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/FileRow.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+import QtQuick.Layouts 1.3
+import QtQuick.Controls 1.0 as Controls
+
+Item {
+ id: root
+ height: 30
+ property string text: "Filename"
+ property bool selected: false
+ signal clicked()
+
+ RowLayout {
+ id: fileRow
+ width: 100
+
+ Item {
+ id: item5
+ width: 10
+ height: 10
+ }
+
+ Rectangle {
+ id: rectangle2
+ width: 10
+ height: 10
+ color: selected ? "#80c342" : "#25a6e2"
+ }
+
+ Text {
+ id: filename
+ text: root.text
+ font.pointSize: 12
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ width: 200
+ height: 30
+ onClicked: root.clicked()
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/JavaScript.qml b/examples/webengine/customdialogs/forms/JavaScript.qml
new file mode 100644
index 000000000..a97d8e0d4
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/JavaScript.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+import QtWebEngine 1.4
+
+JavaScriptForm {
+ property QtObject request
+ signal closeForm()
+
+ cancelButton.onClicked: {
+ request.dialogReject();
+ closeForm();
+ }
+
+ okButton.onClicked: {
+ request.dialogAccept(prompt.text);
+ closeForm();
+ }
+
+ Component.onCompleted: {
+ switch (request.type) {
+ case JavaScriptDialogRequest.DialogTypeAlert:
+ cancelButton.visible = false;
+ title = qsTr("Alert");
+ message = request.message;
+ prompt.text = "";
+ prompt.visible = false;
+ break;
+ case JavaScriptDialogRequest.DialogTypeConfirm:
+ title = qsTr("Confirm");
+ message = request.message;
+ prompt.text = "";
+ prompt.visible = false;
+ break;
+ case JavaScriptDialogRequest.DialogTypePrompt:
+ title = qsTr("Prompt");
+ message = request.message;
+ prompt.text = request.defaultText;
+ prompt.visible = true;
+ break;
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/JavaScriptForm.ui.qml b/examples/webengine/customdialogs/forms/JavaScriptForm.ui.qml
new file mode 100644
index 000000000..cc0c1908e
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/JavaScriptForm.ui.qml
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+import QtQuick.Layouts 1.3
+import QtQuick.Controls 1.0 as Controls
+
+Item {
+ id: item
+ property alias cancelButton: cancelButton
+ property alias okButton: okButton
+ property string message: "Message"
+ property string title: "Title"
+ property alias prompt: prompt
+
+ ColumnLayout {
+ id: columnLayout
+ anchors.topMargin: 20
+ anchors.top: parent.top
+ anchors.bottomMargin: 20
+ anchors.bottom: parent.bottom
+ anchors.rightMargin: 20
+ anchors.right: parent.right
+ anchors.leftMargin: 20
+ anchors.left: parent.left
+
+ Image {
+ id: image
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ source: "qrc:/icon.svg"
+ }
+
+ Rectangle {
+ id: rectangle
+ height: 30
+ anchors.rightMargin: 0
+ anchors.leftMargin: 0
+ anchors.right: parent.right
+ anchors.left: parent.left
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ color: "#25a6e2"
+ }
+
+ GradientStop {
+ color: "#188bd0"
+ }
+ }
+
+ Text {
+ id: title
+ x: 54
+ y: 5
+ color: "#ffffff"
+ text: qsTr("Title")
+ font.pointSize: 12
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+
+ Item {
+ width: 40
+ height: 40
+ }
+
+ Text {
+ id: message
+ text: item.message
+ font.pointSize: 12
+ }
+
+ Controls.TextField {
+ id: prompt
+ width: 300
+ height: 22
+ Layout.fillWidth: true
+ font.pointSize: 12
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+
+ RowLayout {
+ id: rowLayout
+ width: 100
+ height: 100
+
+ Item {
+ Layout.fillWidth: true
+ }
+
+ Button {
+ id: cancelButton
+ width: 90
+ height: 30
+ btnText: qsTr("Cancel")
+ btnBlue: false
+ }
+
+ Button {
+ id: okButton
+ width: 90
+ height: 30
+ btnText: qsTr("OK")
+ btnBlue: false
+ }
+ }
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/Menu.qml b/examples/webengine/customdialogs/forms/Menu.qml
new file mode 100644
index 000000000..1ba6a84b4
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/Menu.qml
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+
+MenuForm {
+ property QtObject request
+ signal closeForm()
+
+ followLink.onClicked: closeForm()
+ back.onClicked: closeForm()
+ forward.onClicked: closeForm()
+ reload.onClicked: closeForm()
+ copyLinkUrl.onClicked: closeForm()
+ saveLink.onClicked: closeForm()
+ close.onClicked: closeForm()
+
+ Component.onCompleted: {
+ back.btnEnable = false;
+ forward.btnEnable = false;
+ }
+}
diff --git a/examples/webengine/customdialogs/forms/MenuForm.ui.qml b/examples/webengine/customdialogs/forms/MenuForm.ui.qml
new file mode 100644
index 000000000..696511cc7
--- /dev/null
+++ b/examples/webengine/customdialogs/forms/MenuForm.ui.qml
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.4
+import QtQuick.Layouts 1.3
+
+Item {
+ property alias followLink: followLink
+ property alias back: back
+ property alias forward: forward
+ property alias reload: reload
+ property alias copyLinkUrl: copyLinkUrl
+ property alias saveLink: saveLink
+ property alias close: close
+
+ ColumnLayout {
+ id: columnLayout
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ Image {
+ id: image
+ width: 100
+ height: 100
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
+ source: "qrc:/icon.svg"
+ }
+
+ Button {
+ id: followLink
+ btnText: qsTr("Follow")
+ }
+
+ Button {
+ id: back
+ btnText: qsTr("Back")
+ }
+
+ Button {
+ id: forward
+ btnText: qsTr("Forward")
+ }
+
+ Button {
+ id: reload
+ btnText: qsTr("Reload")
+ }
+
+ Button {
+ id: copyLinkUrl
+ btnText: qsTr("Copy Link URL")
+ }
+
+ Button {
+ id: saveLink
+ btnText: qsTr("Save Link")
+ }
+
+ Button {
+ id: close
+ btnBlue: false
+ btnText: qsTr("Close")
+ }
+
+ }
+}
diff --git a/examples/webengine/customdialogs/icon.svg b/examples/webengine/customdialogs/icon.svg
new file mode 100644
index 000000000..48271180b
--- /dev/null
+++ b/examples/webengine/customdialogs/icon.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="94px" height="94px" viewBox="0 0 94 94" enable-background="new 0 0 94 94" xml:space="preserve">
+<g>
+ <circle fill="none" cx="47" cy="47" r="47"/>
+ <g>
+ <path fill="#46A2DA" d="M47,92.979c-11.779,0-23.559-4.484-32.526-13.451C-3.461,61.591-3.461,32.409,14.472,14.474
+ C32.41-3.463,61.592-3.461,79.526,14.473c17.935,17.936,17.935,47.119,0.002,65.054l-0.002,0.001
+ C70.559,88.495,58.779,92.979,47,92.979z"/>
+ </g>
+ <path fill="#80C342" d="M93,47C93,21.595,72.405,1,47,1C34.297,1,22.797,6.149,14.473,14.473l65.054,65.054
+ C87.851,71.203,93,59.703,93,47z"/>
+ <g>
+ <path fill="#46A2DA" d="M47,65c-4.808,0-9.328-1.873-12.728-5.272c-7.018-7.019-7.018-18.438,0-25.456
+ C37.672,30.873,42.192,29,47,29s9.328,1.873,12.728,5.272c7.018,7.019,7.018,18.438,0,25.456C56.328,63.127,51.808,65,47,65z"/>
+ <path fill="#FFFFFF" d="M62.248,59.919c6.671-7.858,6.312-19.644-1.105-27.061C57.237,28.953,52.118,27,47,27
+ c-5.118,0-10.237,1.953-14.142,5.858c-7.81,7.81-7.81,20.474,0,28.284C36.763,65.047,41.882,67,47,67
+ c4.379,0,8.752-1.441,12.372-4.3L77.88,81.209c0.989-0.895,1.935-1.837,2.843-2.814L62.248,59.919z M35.686,58.314
+ c-6.238-6.238-6.238-16.389,0-22.627C38.708,32.664,42.726,31,47,31c4.274,0,8.292,1.664,11.314,4.686
+ c6.238,6.238,6.238,16.389,0,22.627C55.292,61.336,51.274,63,47,63C42.726,63,38.708,61.336,35.686,58.314z"/>
+ </g>
+</g>
+</svg>
diff --git a/examples/webengine/customdialogs/index.html b/examples/webengine/customdialogs/index.html
new file mode 100644
index 000000000..43a2dbb67
--- /dev/null
+++ b/examples/webengine/customdialogs/index.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Custom UI</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+ <body>
+ <table align="center">
+ <tr>
+ <td><div class="div"><a href="#openMenu" class="link">Right click on text to see link context menu</a></div></td>
+ </tr>
+ <tr>
+ <td><button class="button" onclick="window.location = 'http://localhost.:5555/OPEN_AUTH'">
+ Open Authentication Dialog</button></td>
+ </tr>
+ <tr>
+ <td><button class="button" onclick="window.location = 'http://localhost.:5555/OPEN_PROXY'">
+ Open Proxy Dialog</button></td>
+ </tr>
+ <tr>
+ <td><button class="button" onclick="alert('This is the Alert Dialog !')">
+ Open Alert Dialog</button></td>
+ </tr>
+ <tr>
+ <td><button class="button" onclick="confirm('This is the Confirm Dialog.')">
+ Open Confirm Dialog</button></td>
+ </tr>
+ <tr>
+ <td><button class="button" onclick="prompt('Is this the Prompt Dialog ?', 'Yes')">
+ Open Prompt Dialog</button></td>
+ </tr>
+ <tr>
+ <td><button class="button" onclick="document.getElementById('colorpicker').click()">
+ Open Color Dialog</button></td>
+ </tr>
+ <tr>
+ <td><button class="button" onclick="document.getElementById('filepicker').click()">
+ Open File Dialog</button></td>
+ </tr>
+ <tr>
+ <td>
+ <form><table>
+ <tr><td><button class="button" type="submit">Open Message Bubble</button></td></tr>
+ <tr><td><input class="input" placeholder="For this field we open message bubble..." required/></td></tr>
+ </table></form>
+ </td>
+ </tr>
+ </table>
+ <input type="color" id="colorpicker" value="#ff0000" style="visibility:hidden"/>
+ <input type="file" id="filepicker" accept=".cpp, .html, .h, .png, .qdoc, .qml" style="visibility:hidden"/>
+ </body>
+</html>
diff --git a/examples/webengine/customdialogs/main.cpp b/examples/webengine/customdialogs/main.cpp
new file mode 100644
index 000000000..2f79a1e48
--- /dev/null
+++ b/examples/webengine/customdialogs/main.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "server.h"
+#include <qtwebengineglobal.h>
+#include <QNetworkProxy>
+#include <QQmlApplicationEngine>
+#include <QTimer>
+
+#ifndef QT_NO_WIDGETS
+#include <QtWidgets/QApplication>
+// QApplication is required to get native styling with QtQuickControls
+typedef QApplication Application;
+#else
+#include <QtGui/QGuiApplication>
+typedef QGuiApplication Application;
+#endif
+
+int main(int argc, char *argv[])
+{
+ Application app(argc, argv);
+ QtWebEngine::initialize();
+
+ QQmlApplicationEngine engine;
+ Server *server = new Server(&engine);
+
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+ QTimer::singleShot(0, server, &Server::run);
+
+ QNetworkProxy proxy;
+ proxy.setType(QNetworkProxy::HttpProxy);
+ proxy.setHostName("localhost");
+ proxy.setPort(5555);
+ QNetworkProxy::setApplicationProxy(proxy);
+
+ return app.exec();
+}
+
diff --git a/examples/webengine/customdialogs/main.qml b/examples/webengine/customdialogs/main.qml
new file mode 100644
index 000000000..4288137fc
--- /dev/null
+++ b/examples/webengine/customdialogs/main.qml
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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.0
+import QtQuick.Controls 1.4 as Controls
+import QtQuick.Layouts 1.3
+import QtQuick.Window 2.0
+
+Window {
+ width: 350
+ height: 550
+ visible: true
+
+ Controls.StackView {
+ id: stackView
+ anchors.fill: parent
+ focus: true
+ initialItem: Item {
+ id: main
+ width: parent.width
+ height: parent.height
+ ColumnLayout {
+ anchors.fill: parent
+ SwitchButton {
+ id: switcher
+ Layout.fillWidth: true
+ }
+ WebView {
+ id: webView
+ useDefaultDialogs: switcher.checked
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ }
+ }
+ }
+
+ function closeForm()
+ {
+ pop(main);
+ }
+
+ function openForm(form)
+ {
+ push(form);
+ currentItem.closeForm.connect(closeForm);
+ }
+
+ }
+
+ Component.onCompleted: {
+ webView.openForm.connect(stackView.openForm);
+ }
+}
diff --git a/examples/webengine/customdialogs/server.cpp b/examples/webengine/customdialogs/server.cpp
new file mode 100644
index 000000000..21a8ffe5a
--- /dev/null
+++ b/examples/webengine/customdialogs/server.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "server.h"
+#include <QDataStream>
+#include <QTcpSocket>
+
+Server::Server(QObject *parent) : QObject(parent)
+{
+ connect(&m_server, &QTcpServer::newConnection, this, &Server::handleNewConnection);
+}
+
+void Server::run()
+{
+ if (!m_server.listen(QHostAddress::LocalHost, 5555))
+ qWarning() << "Could not start the server -> http/proxy authentication dialog"
+ " will not work. Error:" << m_server.errorString();
+}
+
+void Server::handleNewConnection()
+{
+ QTcpSocket *socket = m_server.nextPendingConnection();
+ connect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater);
+ connect(socket, &QAbstractSocket::readyRead, this, &Server::handleReadReady);
+}
+
+void Server::handleReadReady()
+{
+ QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
+ Q_ASSERT(socket);
+ QByteArray msg = socket->readAll();
+ if (msg.contains(QByteArrayLiteral("OPEN_AUTH")))
+ socket->write("HTTP/1.1 401 Unauthorized\nWWW-Authenticate: "
+ "Basic realm=\"Very Restricted Area\"\r\n\r\n");
+ if (msg.contains(QByteArrayLiteral("OPEN_PROXY")))
+ socket->write("HTTP/1.1 407 Proxy Auth Required\nProxy-Authenticate: "
+ "Basic realm=\"Proxy requires authentication\"\r\n\r\n");
+}
diff --git a/examples/webengine/customdialogs/server.h b/examples/webengine/customdialogs/server.h
new file mode 100644
index 000000000..dc96acb70
--- /dev/null
+++ b/examples/webengine/customdialogs/server.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#ifndef SERVER_H
+#define SERVER_H
+
+#include <QObject>
+#include <QTcpServer>
+
+class Server : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit Server(QObject *parent = nullptr);
+
+public slots:
+ void run();
+
+private slots:
+ void handleNewConnection();
+ void handleReadReady();
+
+private:
+ QTcpServer m_server;
+};
+
+#endif // SERVER_H
diff --git a/examples/webengine/customdialogs/style.css b/examples/webengine/customdialogs/style.css
new file mode 100644
index 000000000..e4c25e7eb
--- /dev/null
+++ b/examples/webengine/customdialogs/style.css
@@ -0,0 +1,37 @@
+.div {
+ padding:8px 4px;
+ border: 5px solid #188BD0;
+ width: 280px;
+ font-family: sans-serif;
+ font-size:10pt;
+}
+.link {
+ text-decoration: none;
+ color: #888888;
+}
+.button {
+ background: -webkit-linear-gradient(top,#25A6E2 0%,#188BD0 100%);
+ padding:8px 13px;
+ color:#fff;
+ font-family: sans-serif;
+ font-size:17px;
+ -webkit-border-radius:5px;
+ border:1px solid #1A87FF;
+ width: 300px;
+}
+.button:focus {
+ outline: none;
+}
+.button:active {
+ background: -webkit-linear-gradient(top,#25A6E2 0%,#188BD0 70%);
+}
+.input {
+ padding:8px 4px;
+ border: 5px solid #188BD0;
+ width: 280px;
+ font-family: sans-serif;
+ font-size:10pt;
+}
+.input:focus {
+ outline: none;
+}
diff --git a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp
index 6f66e5048..926c4a5d7 100644
--- a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp
+++ b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp
@@ -758,6 +758,8 @@ void BrowserMainWindow::slotFilePrintToPDF()
#ifndef QT_NO_PRINTER
void BrowserMainWindow::slotHandlePagePrinted(bool result)
{
+ Q_UNUSED(result);
+
delete m_currentPrinter;
m_currentPrinter = nullptr;
}
diff --git a/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc b/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc
index d5b972b93..b0240cd4d 100644
--- a/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc
+++ b/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc
@@ -41,12 +41,12 @@
\section1 Dictionaries
To be able to check the spelling, we need to provide the spellchecker with
- dictionaries. In this example, we want to support the English and German
- languages.
+ dictionaries. The Qt WebEngine spellchecker supports dictionaries provided by the
+ \l {Hunspell project} on all platforms and native dictionaries provided by macOS.
+ In this example, we want to support the English and German languages.
- The Qt WebEngine spellchecker supports dictionaries from the
- \l{Hunspell project}, but they have to be compiled into a special binary
- format. A Hunspell dictionary consists of two files:
+ For Hunspell dictionaries to be supported they have to be compiled into a special binary format.
+ A Hunspell dictionary consists of two files:
\list
@@ -78,7 +78,12 @@
When a specific spellchecking language is requested, Qt WebEngine will try
to load the already compiled matching \c .bdic file first from
\e qtwebengine_dictionaries directories relative to the executable,
- then it will look in \c QT_INSTALL_PREFIX/qtwebengines_dictionaries.
+ then it will look in \c QT_INSTALL_PREFIX/qtwebengine_dictionaries.
+
+ On macOS, because this example was configured to use Hunspell dictionaries, Qt WebEngine will
+ look in the \e qtwebengine_dictionaries directory located inside the application bundle
+ \c Resources directory, and also in the \c Resources directory located inside the
+ Qt framework bundle.
We specify the QMAKE_EXTRA_COMPILERS parameter in the project file to add a
conversion step to the build process:
@@ -87,11 +92,11 @@
\skipto CONVERT_TOOL
\printuntil QMAKE_EXTRA_COMPILERS
- To set up a dictionary, we run \c qwebengine_convert_dic passing the
+ To set up a dictionary, we run \c qwebengine_convert_dict passing the
file path of the dictionary \c dic and \c bdic files. The \c aff file and
optional \c delta file are also picked up by the \c convert process.
The output \c bdic file is placed into the \e qtwebengine_dictionaries local
- directory, which the application binary will run from.
+ directory (or Resources directory), which the application binary will run from.
\section1 Setting the Spellchecker
diff --git a/examples/webenginewidgets/spellchecker/spellchecker.pro b/examples/webenginewidgets/spellchecker/spellchecker.pro
index c7bee6584..c6031a36d 100644
--- a/examples/webenginewidgets/spellchecker/spellchecker.pro
+++ b/examples/webenginewidgets/spellchecker/spellchecker.pro
@@ -3,6 +3,10 @@ TARGET = spellchecker
QT += webenginewidgets
CONFIG += c++11
+contains(WEBENGINE_CONFIG, use_native_spellchecker) {
+ error("Spellcheck example can not be built when using native OS dictionaries.")
+}
+
HEADERS += \
webview.h
@@ -33,7 +37,11 @@ debug_and_release {
DICTIONARIES_DIR = qtwebengine_dictionaries
}
-dict.files = $$PWD/dict/en/en-US.dic $$PWD/dict/de/de-DE.dic
+dict_base_paths = en/en-US de/de-DE
+for (base_path, dict_base_paths) {
+ dict.files += $$PWD/dict/$${base_path}.dic
+}
+
dictoolbuild.input = dict.files
dictoolbuild.output = $${DICTIONARIES_DIR}/${QMAKE_FILE_BASE}.bdic
dictoolbuild.depends = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.aff
@@ -41,3 +49,15 @@ dictoolbuild.commands = $${CONVERT_TOOL} ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
dictoolbuild.name = Build ${QMAKE_FILE_IN_BASE}
dictoolbuild.CONFIG = no_link target_predeps
QMAKE_EXTRA_COMPILERS += dictoolbuild
+
+# When the example is compiled as a bundle, WebEngine expects to find the dictionaries in
+# bundle.app/Contents/Resources/qtwebengine_dictionaries
+macos:app_bundle {
+ for (base_path, dict_base_paths) {
+ base_path_splitted = $$split(base_path, /)
+ base_name = $$last(base_path_splitted)
+ binary_dict_files.files += $${DICTIONARIES_DIR}/$${base_name}.bdic
+ }
+ binary_dict_files.path = Contents/Resources/$$DICTIONARIES_DIR
+ QMAKE_BUNDLE_DATA += binary_dict_files
+}
diff --git a/examples/webenginewidgets/spellchecker/webview.cpp b/examples/webenginewidgets/spellchecker/webview.cpp
index 6c73d88fa..86e21ab13 100644
--- a/examples/webenginewidgets/spellchecker/webview.cpp
+++ b/examples/webenginewidgets/spellchecker/webview.cpp
@@ -51,7 +51,7 @@ WebView::WebView(QWidget *parent)
m_spellCheckLanguages["German"] = "de-DE";
QWebEngineProfile *profile = page()->profile();
profile->setSpellCheckEnabled(true);
- profile->setSpellCheckLanguage("en-US");
+ profile->setSpellCheckLanguages({"en-US"});
}
void WebView::contextMenuEvent(QContextMenuEvent *event)
@@ -65,7 +65,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)
}
QWebEngineProfile *profile = page()->profile();
- const QString &language = profile->spellCheckLanguage();
+ const QString &language = profile->spellCheckLanguages().first();
QMenu *menu = page()->createStandardContextMenu();
menu->addSeparator();
@@ -85,7 +85,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)
QString lang = m_spellCheckLanguages[str];
action->setChecked(language == lang);
connect(action, &QAction::triggered, this, [profile, lang](){
- profile->setSpellCheckLanguage(lang);
+ profile->setSpellCheckLanguages(QStringList()<<lang);
});
}
}
diff --git a/qtwebengine.pro b/qtwebengine.pro
index 3d20cc2f4..3fd5c12e6 100644
--- a/qtwebengine.pro
+++ b/qtwebengine.pro
@@ -1,6 +1,19 @@
load(qt_build_config)
load(qt_parts)
+isPlatformSupported() {
+ !exists(src/3rdparty/chromium): \
+ error("Submodule qtwebengine-chromium does not exist. Run 'git submodule update --init'.")
+ load(configure)
+ runConfigure()
+}
+
+!isEmpty(skipBuildReason) {
+ SUBDIRS =
+ log($${skipBuildReason}$${EOL})
+ log(QtWebEngine will not be built.$${EOL})
+}
+
OTHER_FILES = \
tools/buildscripts/* \
tools/scripts/* \
diff --git a/src/3rdparty b/src/3rdparty
-Subproject 7824a683f0d5c93e6b8fd5dfc75d51d06167f0c
+Subproject f5a732820b31651bafc60cd64f85b85c7f82532
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index cb9d33087..37f8885bb 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -15,9 +15,7 @@ CONFIG -= create_prl
# Copy this logic from qt_module.prf so that the intermediate library can be
# created to the same rules as the final module linking in core_module.pro.
!host_build:if(win32|mac):!macx-xcode {
- qtConfig(simulator_and_device): CONFIG += simulator_and_device
- qtConfig(debug_and_release): CONFIG += debug_and_release
- qtConfig(build_all): CONFIG += build_all
+ qtConfig(debug_and_release): CONFIG += debug_and_release build_all
}
DEFINES += \
diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp
index 86808e177..3396f73ef 100644
--- a/src/core/browser_context_adapter.cpp
+++ b/src/core/browser_context_adapter.cpp
@@ -491,19 +491,19 @@ void BrowserContextAdapter::clearHttpCache()
m_browserContext->url_request_getter_->clearHttpCache();
}
-void BrowserContextAdapter::setSpellCheckLanguage(const QString &language)
+void BrowserContextAdapter::setSpellCheckLanguages(const QStringList &languages)
{
#if defined(ENABLE_SPELLCHECK)
- m_browserContext->setSpellCheckLanguage(language);
+ m_browserContext->setSpellCheckLanguages(languages);
#endif
}
-QString BrowserContextAdapter::spellCheckLanguage() const
+QStringList BrowserContextAdapter::spellCheckLanguages() const
{
#if defined(ENABLE_SPELLCHECK)
- return m_browserContext->spellCheckLanguage();
+ return m_browserContext->spellCheckLanguages();
#else
- return QString();
+ return QStringList();
#endif
}
diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h
index a6e5a2a3e..39b9db61c 100644
--- a/src/core/browser_context_adapter.h
+++ b/src/core/browser_context_adapter.h
@@ -108,9 +108,8 @@ public:
QString httpUserAgent() const;
void setHttpUserAgent(const QString &userAgent);
- QStringList spellCheckLanguages(const QStringList &acceptLanguages);
- void setSpellCheckLanguage(const QString &language);
- QString spellCheckLanguage() const;
+ void setSpellCheckLanguages(const QStringList &language);
+ QStringList spellCheckLanguages() const;
void setSpellCheckEnabled(bool enabled);
bool isSpellCheckEnabled() const;
diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp
index 5f544ab86..a6801e1d7 100644
--- a/src/core/browser_context_qt.cpp
+++ b/src/core/browser_context_qt.cpp
@@ -213,18 +213,27 @@ void BrowserContextQt::failedToLoadDictionary(const std::string &language)
<< "Make sure that correct bdic file is in:" << toQt(WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES).value());
}
-void BrowserContextQt::setSpellCheckLanguage(const QString &language)
+void BrowserContextQt::setSpellCheckLanguages(const QStringList &languages)
{
- base::ListValue dictionaries;
- dictionaries.AppendString(language.toStdString());
- m_prefService->Set(prefs::kSpellCheckDictionaries, dictionaries);
+ StringListPrefMember dictionaries_pref;
+ dictionaries_pref.Init(prefs::kSpellCheckDictionaries, m_prefService.get());
+ std::vector<std::string> dictionaries;
+ dictionaries.reserve(languages.size());
+ for (const auto &language : languages)
+ dictionaries.push_back(language.toStdString());
+ dictionaries_pref.SetValue(dictionaries);
}
-QString BrowserContextQt::spellCheckLanguage() const
+QStringList BrowserContextQt::spellCheckLanguages() const
{
- std::string dictionary;
- m_prefService->GetList(prefs::kSpellCheckDictionaries)->GetString(0, &dictionary);
- return QString::fromStdString(dictionary);
+ QStringList spellcheck_dictionaries;
+ for (const auto &value : *m_prefService->GetList(prefs::kSpellCheckDictionaries)) {
+ std::string dictionary;
+ if (value->GetAsString(&dictionary))
+ spellcheck_dictionaries.append(QString::fromStdString(dictionary));
+ }
+
+ return spellcheck_dictionaries;
}
void BrowserContextQt::setSpellCheckEnabled(bool enabled)
diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h
index 41a85b1b0..ca65552be 100644
--- a/src/core/browser_context_qt.h
+++ b/src/core/browser_context_qt.h
@@ -101,9 +101,9 @@ public:
BrowserContextAdapter *adapter() { return m_adapter; }
#if defined(ENABLE_SPELLCHECK)
- void failedToLoadDictionary(const std::string& language);
- void setSpellCheckLanguage(const QString &language);
- QString spellCheckLanguage() const;
+ void failedToLoadDictionary(const std::string& language) override;
+ void setSpellCheckLanguages(const QStringList &languages);
+ QStringList spellCheckLanguages() const;
void setSpellCheckEnabled(bool enabled);
bool isSpellCheckEnabled() const;
#endif
diff --git a/src/core/chrome_qt.gyp b/src/core/chrome_qt.gyp
index 547f240ea..89f1fe188 100644
--- a/src/core/chrome_qt.gyp
+++ b/src/core/chrome_qt.gyp
@@ -113,7 +113,7 @@
'<(chromium_src_dir)/third_party/WebKit',
],
'dependencies': [
- '<(chromium_src_dir)/chrome/tools/convert_dict/convert_dict.gyp:convert_dict_lib',
+ '<(chromium_src_dir)/chrome/tools/convert_dict/convert_dict.gyp:convert_dict',
'<(chromium_src_dir)/third_party/hunspell/hunspell.gyp:hunspell',
'<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n',
'<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
@@ -132,6 +132,8 @@
'sources!': [
'<(DEPTH)/chrome/renderer/spellchecker/platform_spelling_engine.cc',
'<(DEPTH)/chrome/renderer/spellchecker/platform_spelling_engine.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_message_filter_platform.h',
+ '<(DEPTH)/chrome/browser/spellchecker/spellcheck_message_filter_platform_mac.cc',
],
}],
],
diff --git a/src/core/config/common.pri b/src/core/config/common.pri
index 01c942976..7a9656fca 100644
--- a/src/core/config/common.pri
+++ b/src/core/config/common.pri
@@ -10,3 +10,8 @@ GYP_CONFIG += v8_use_external_startup_data=0
GYP_CONFIG += enable_web_speech=0
# We do not use or even include the extensions
GYP_CONFIG += enable_extensions=0
+
+sanitize_address: GYP_CONFIG += asan=1
+sanitize_thread: GYP_CONFIG += tsan=1
+sanitize_memory: GYP_CONFIG += msan=1
+sanitize_undefined: GYP_CONFIG += ubsan=1
diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri
index 46d500207..e28d7eb7c 100644
--- a/src/core/config/desktop_linux.pri
+++ b/src/core/config/desktop_linux.pri
@@ -8,7 +8,11 @@ GYP_CONFIG += \
enable_pdf=1
clang {
- GYP_CONFIG += clang=1 host_clang=1 clang_use_chrome_plugins=0 make_clang_dir=/usr
+ GYP_CONFIG += werror=
+ clang_full_path = $$which($${QMAKE_CXX})
+ # Remove the "/bin/clang++" part.
+ clang_prefix = $$section(clang_full_path, /, 0, -3)
+ GYP_CONFIG += clang=1 host_clang=1 clang_use_chrome_plugins=0 make_clang_dir=$${clang_prefix}
linux-clang-libc++: GYP_CONFIG += use_system_libcxx=1
} else {
GYP_CONFIG += clang=0 host_clang=0
diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri
index fc2b124fb..83c852f86 100644
--- a/src/core/config/linux.pri
+++ b/src/core/config/linux.pri
@@ -39,7 +39,7 @@ gcc:!clang: greaterThan(QT_GCC_MAJOR_VERSION, 5): GYP_CONFIG += no_delete_null_p
qtConfig(system-zlib): use?(system_minizip): GYP_CONFIG += use_system_zlib=1
qtConfig(system-png): GYP_CONFIG += use_system_libpng=1
qtConfig(system-jpeg): GYP_CONFIG += use_system_libjpeg=1
-qtConfig(system-harfbuzz): GYP_CONFIG += use_system_harfbuzz=1
+qtConfig(system-harfbuzz): use?(system_harfbuzz): GYP_CONFIG += use_system_harfbuzz=1
!qtConfig(glib): GYP_CONFIG += use_glib=0
contains(QT_CONFIG, pulseaudio) {
GYP_CONFIG += use_pulseaudio=1
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index 64964dc09..787586540 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -44,11 +44,15 @@
#include "base/threading/thread_restrictions.h"
#if defined(ENABLE_SPELLCHECK)
#include "chrome/browser/spellchecker/spellcheck_message_filter.h"
+#if defined(USE_BROWSER_SPELLCHECKER)
+#include "chrome/browser/spellchecker/spellcheck_message_filter_platform.h"
+#endif
#endif
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/public/browser/browser_main_parts.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/geolocation_delegate.h"
+#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/media_observer.h"
#include "content/public/browser/quota_permission_context.h"
#include "content/public/browser/render_frame_host.h"
@@ -81,6 +85,7 @@
#if defined(ENABLE_BASIC_PRINTING)
#include "printing_message_filter_qt.h"
#endif // defined(ENABLE_BASIC_PRINTING)
+#include "qrc_protocol_handler_qt.h"
#include "renderer_host/resource_dispatcher_host_delegate_qt.h"
#include "renderer_host/user_resource_controller_host.h"
#include "web_contents_delegate_qt.h"
@@ -280,7 +285,8 @@ public:
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext);
else if (platform == QLatin1String("qnx"))
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext);
- else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland"))
+ else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland")
+ || platform == QLatin1String("wayland-egl"))
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext);
else if (platform == QLatin1String("windows")) {
if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2)
@@ -377,8 +383,12 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost*
host->AddFilter(new BrowserMessageFilterQt(id));
#endif
#if defined(ENABLE_SPELLCHECK)
+ // SpellCheckMessageFilter is required for both Hunspell and Native configurations.
host->AddFilter(new SpellCheckMessageFilter(id));
#endif
+#if defined(Q_OS_MACOS) && defined(USE_BROWSER_SPELLCHECKER)
+ host->AddFilter(new SpellCheckMessageFilterPlatform(id));
+#endif
#if defined(ENABLE_BASIC_PRINTING)
host->AddFilter(new PrintingMessageFilterQt(host->GetID()));
#endif // defined(ENABLE_BASIC_PRINTING)
@@ -472,6 +482,13 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont
*result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
}
+void ContentBrowserClientQt::SelectClientCertificate(content::WebContents * /*webContents*/,
+ net::SSLCertRequestInfo * /*certRequestInfo*/,
+ std::unique_ptr<content::ClientCertificateDelegate> delegate)
+{
+ delegate->ContinueWithCertificate(nullptr);
+}
+
std::string ContentBrowserClientQt::GetApplicationLocale()
{
return WebEngineLibraryInfo::getApplicationLocale();
@@ -491,6 +508,11 @@ void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* c
command_line->AppendSwitchASCII(switches::kLang, GetApplicationLocale());
}
+void ContentBrowserClientQt::GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes)
+{
+ additional_schemes->push_back(kQrcSchemeQt);
+}
+
#if defined(Q_OS_LINUX)
void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::FileDescriptorInfo* mappings)
{
diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h
index acbf1a059..a13d14ff2 100644
--- a/src/core/content_browser_client_qt.h
+++ b/src/core/content_browser_client_qt.h
@@ -100,11 +100,15 @@ public:
bool expired_previous_decision,
const base::Callback<void(bool)>& callback,
content::CertificateRequestResultType* result) Q_DECL_OVERRIDE;
+ virtual void SelectClientCertificate(content::WebContents* web_contents,
+ net::SSLCertRequestInfo* cert_request_info,
+ std::unique_ptr<content::ClientCertificateDelegate> delegate) Q_DECL_OVERRIDE;
content::DevToolsManagerDelegate *GetDevToolsManagerDelegate() Q_DECL_OVERRIDE;
virtual std::string GetApplicationLocale() Q_DECL_OVERRIDE;
std::string GetAcceptLangs(content::BrowserContext* context) Q_DECL_OVERRIDE;
virtual void AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) Q_DECL_OVERRIDE;
+ virtual void GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) Q_DECL_OVERRIDE;
#if defined(Q_OS_LINUX)
virtual void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::FileDescriptorInfo* mappings) Q_DECL_OVERRIDE;
diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp
index 0dac5e48b..5d51f65aa 100644
--- a/src/core/content_client_qt.cpp
+++ b/src/core/content_client_qt.cpp
@@ -166,7 +166,8 @@ void AddPepperFlashFromSystem(std::vector<content::PepperPluginInfo>* plugins)
#endif
#if defined(Q_OS_LINUX)
pluginPaths << "/opt/google/chrome/PepperFlash/libpepflashplayer.so" // Google Chrome
- << "/usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so" // Ubuntu
+ << "/usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so" // Ubuntu, package pepperflashplugin-nonfree
+ << "/usr/lib/adobe-flashplugin/libpepflashplayer.so" // Ubuntu, package adobe-flashplugin
<< "/usr/lib/PepperFlash/libpepflashplayer.so" // Arch
<< "/usr/lib64/chromium/PepperFlash/libpepflashplayer.so"; // OpenSuSE
pluginPaths << ppapiPluginsPath() + QStringLiteral("/libpepflashplayer.so");
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index 44e37aeb6..baf064025 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -111,6 +111,10 @@
#define GL_RGB 0x1907
#endif
+#ifndef GL_LINE_LOOP
+#define GL_LINE_LOOP 0x0002
+#endif
+
namespace QtWebEngineCore {
#ifndef QT_NO_OPENGL
class MailboxTexture : public QSGTexture, protected QOpenGLFunctions {
@@ -642,7 +646,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
QSGGeometryNode *geometryNode = new QSGGeometryNode;
QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
- geometry->setDrawingMode(QSGGeometry::DrawLineLoop);
+ geometry->setDrawingMode(GL_LINE_LOOP);
geometry->setLineWidth(dbquad->width);
// QSGGeometry::updateRectGeometry would actually set the corners in the following order:
// top-left, bottom-left, top-right, bottom-right, leading to a nice criss cross, instead
diff --git a/src/core/doc/src/qtwebenginecore-index.qdoc b/src/core/doc/src/qtwebenginecore-index.qdoc
index 70af397ce..4d540e277 100644
--- a/src/core/doc/src/qtwebenginecore-index.qdoc
+++ b/src/core/doc/src/qtwebenginecore-index.qdoc
@@ -28,7 +28,6 @@
/*!
\page qtwebenginecore-index.html
\title Qt WebEngine Core
- \ingroup modules
\brief Provides common API shared by Qt WebEngine and Qt WebEngine Widgets.
diff --git a/src/core/doc/src/qtwebenginecore-module.qdoc b/src/core/doc/src/qtwebenginecore-module.qdoc
index 6dc2478fc..0ac20a794 100644
--- a/src/core/doc/src/qtwebenginecore-module.qdoc
+++ b/src/core/doc/src/qtwebenginecore-module.qdoc
@@ -32,6 +32,7 @@
\brief Provides public API shared by both QtWebEngine and QtWebEngineWidgets
\since 5.6
\ingroup qtwebengine-modules
+ \ingroup modules
To include the definitions of the module's classes, use the
following directive:
diff --git a/src/core/gl_context_qt.cpp b/src/core/gl_context_qt.cpp
index b1177a998..a1855b060 100644
--- a/src/core/gl_context_qt.cpp
+++ b/src/core/gl_context_qt.cpp
@@ -122,7 +122,7 @@ void* GLContextHelper::getXConfig()
void* GLContextHelper::getEGLDisplay()
{
- return resourceForContext(QByteArrayLiteral("egldisplay"));
+ return resourceForIntegration(QByteArrayLiteral("egldisplay"));
}
void* GLContextHelper::getXDisplay()
diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp
index e88a26715..74bb32d1f 100644
--- a/src/core/gl_surface_qt.cpp
+++ b/src/core/gl_surface_qt.cpp
@@ -90,6 +90,9 @@ void* g_display;
const char* g_extensions = NULL;
bool g_egl_surfaceless_context_supported = false;
+
+bool g_initializedEGL = false;
+
} // namespace
@@ -573,11 +576,17 @@ bool InitializeGLOneOffPlatform()
return GLSurfaceQtEGL::InitializeOneOff();
if (GetGLImplementation() == kGLImplementationDesktopGL) {
-#if defined(USE_X11)
- return GLSurfaceQtGLX::InitializeOneOff();
-#elif defined(OS_WIN)
+#if defined(OS_WIN)
return GLSurfaceQtWGL::InitializeOneOff();
+#elif defined(USE_X11)
+ if (GLSurfaceQtGLX::InitializeOneOff())
+ return true;
#endif
+ // Fallback to trying EGL with desktop GL.
+ if (GLSurfaceQtEGL::InitializeOneOff()) {
+ g_initializedEGL = true;
+ return true;
+ }
}
return false;
@@ -586,40 +595,40 @@ bool InitializeGLOneOffPlatform()
scoped_refptr<GLSurface>
CreateOffscreenGLSurface(const gfx::Size& size)
{
+ scoped_refptr<GLSurface> surface;
switch (GetGLImplementation()) {
case kGLImplementationDesktopGLCoreProfile:
case kGLImplementationDesktopGL: {
-#if defined(USE_X11)
- scoped_refptr<GLSurface> surface = new GLSurfaceQtGLX(size);
- if (!surface->Initialize())
- return NULL;
- return surface;
-#elif defined(OS_WIN)
- scoped_refptr<GLSurface> surface = new GLSurfaceQtWGL(size);
- if (!surface->Initialize())
- return NULL;
- return surface;
-#else
- LOG(ERROR) << "Desktop GL is not supported on this platform.";
- Q_UNREACHABLE();
- return NULL;
+#if defined(OS_WIN)
+ surface = new GLSurfaceQtWGL(size);
+ if (surface->Initialize())
+ return surface;
+ break;
+#elif defined(USE_X11)
+ if (!g_initializedEGL) {
+ surface = new GLSurfaceQtGLX(size);
+ if (surface->Initialize())
+ return surface;
+ }
+ // no break
#endif
}
case kGLImplementationEGLGLES2: {
- scoped_refptr<GLSurface> surface;
if (g_egl_surfaceless_context_supported)
surface = new GLSurfacelessQtEGL(size);
else
surface = new GLSurfaceQtEGL(size);
- if (!surface->Initialize())
- return NULL;
- return surface;
+ if (surface->Initialize())
+ return surface;
+ break;
}
default:
- Q_UNREACHABLE();
- return NULL;
+ break;
}
+ LOG(ERROR) << "Requested OpenGL platform is not supported.";
+ Q_UNREACHABLE();
+ return NULL;
}
scoped_refptr<GLSurface>
diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro
index 89b751c4a..1850447e7 100644
--- a/src/core/gyp_run.pro
+++ b/src/core/gyp_run.pro
@@ -36,9 +36,7 @@ force_debug_info {
# Copy this logic from qt_module.prf so that ninja can run according
# to the same rules as the final module linking in core_module.pro.
!host_build:if(win32|mac):!macx-xcode {
- qtConfig(simulator_and_device): CONFIG += simulator_and_device
- qtConfig(debug_and_release): CONFIG += debug_and_release
- qtConfig(build_all): CONFIG += build_all
+ qtConfig(debug_and_release): CONFIG += debug_and_release build_all
}
cross_compile {
@@ -122,12 +120,18 @@ contains(WEBENGINE_CONFIG, use_appstore_compliant_code): GYP_CONFIG += appstore_
# but the latter are necessary for useful debug binaries.
contains(WEBENGINE_CONFIG, reduce_binary_size): GYP_CONFIG += release_optimize=s debug_optimize=s release_unwind_tables=0
-contains(WEBENGINE_CONFIG, no_spellcheck): {
+!contains(WEBENGINE_CONFIG, use_spellchecker): {
GYP_CONFIG += enable_spellcheck=0
- osx: GYP_CONFIG += use_browser_spellchecker=0
+ macos: GYP_CONFIG += use_browser_spellchecker=0
} else {
GYP_CONFIG += enable_spellcheck=1
- osx: GYP_CONFIG += use_browser_spellchecker=1
+ macos {
+ contains(WEBENGINE_CONFIG, use_native_spellchecker) {
+ GYP_CONFIG += use_browser_spellchecker=1
+ } else {
+ GYP_CONFIG += use_browser_spellchecker=0
+ }
+ }
}
!qtConfig(framework):qtConfig(private_tests) {
diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp
index 3e260587c..f06f0150f 100644
--- a/src/core/media_capture_devices_dispatcher.cpp
+++ b/src/core/media_capture_devices_dispatcher.cpp
@@ -173,7 +173,6 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content:
if (securityOriginsMatch && (microphoneRequested || webcamRequested)) {
switch (request.request_type) {
case content::MEDIA_OPEN_DEVICE_PEPPER_ONLY:
- Q_UNREACHABLE(); // only speculative as this is for Pepper
getDefaultDevices("", "", microphoneRequested, webcamRequested, &devices);
break;
case content::MEDIA_DEVICE_ACCESS:
diff --git a/src/core/pdfium_printing_wrapper_qt.cpp b/src/core/pdfium_printing_wrapper_qt.cpp
index 165ac743f..fceb381af 100644
--- a/src/core/pdfium_printing_wrapper_qt.cpp
+++ b/src/core/pdfium_printing_wrapper_qt.cpp
@@ -139,7 +139,9 @@ PdfiumPrintingWrapperQt::PdfiumPrintingWrapperQt(const void *pdfData, size_t siz
bool PdfiumPrintingWrapperQt::printOnPrinter(QPrinter &printer)
{
if (!m_documentHandle || !m_pageCount) {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
qWarning("Failure to print on printer %ls: invalid document.\n", qUtf16Printable(printer.printerName()));
+#endif
return false;
}
@@ -172,7 +174,9 @@ bool PdfiumPrintingWrapperQt::printOnPrinter(QPrinter &printer)
QPainter painter;
if (!painter.begin(&printer)) {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
qWarning("Failure to print on printer %ls: Could not open printer for painting.\n", qUtf16Printable(printer.printerName()));
+#endif
return false;
}
diff --git a/src/core/print_view_manager_qt.cpp b/src/core/print_view_manager_qt.cpp
index 8f52cc24a..0231df8bd 100644
--- a/src/core/print_view_manager_qt.cpp
+++ b/src/core/print_view_manager_qt.cpp
@@ -136,14 +136,16 @@ static base::DictionaryValue *createPrintSettings()
return printSettings;
}
-static void applyQPageLayoutSettingsToDictionary(const QPageLayout &pageLayout, base::DictionaryValue &printSettings)
+static base::DictionaryValue *createPrintSettingsFromQPageLayout(const QPageLayout &pageLayout)
{
+ base::DictionaryValue *printSettings = createPrintSettings();
+
//Set page size attributes, chromium expects these in micrometers
QSizeF pageSizeInMilimeter = pageLayout.pageSize().size(QPageSize::Millimeter);
std::unique_ptr<base::DictionaryValue> sizeDict(new base::DictionaryValue);
sizeDict->SetInteger(printing::kSettingMediaSizeWidthMicrons, pageSizeInMilimeter.width() * kMicronsToMillimeter);
sizeDict->SetInteger(printing::kSettingMediaSizeHeightMicrons, pageSizeInMilimeter.height() * kMicronsToMillimeter);
- printSettings.Set(printing::kSettingMediaSize, std::move(sizeDict));
+ printSettings->Set(printing::kSettingMediaSize, std::move(sizeDict));
// Apply page margins
QMargins pageMarginsInPoints = pageLayout.marginsPoints();
@@ -152,10 +154,13 @@ static void applyQPageLayoutSettingsToDictionary(const QPageLayout &pageLayout,
marginsDict->SetInteger(printing::kSettingMarginBottom, pageMarginsInPoints.bottom());
marginsDict->SetInteger(printing::kSettingMarginLeft, pageMarginsInPoints.left());
marginsDict->SetInteger(printing::kSettingMarginRight, pageMarginsInPoints.right());
- printSettings.Set(printing::kSettingMarginsCustom, std::move(marginsDict));
- printSettings.SetInteger(printing::kSettingMarginsType, printing::CUSTOM_MARGINS);
- printSettings.SetBoolean(printing::kSettingLandscape, pageLayout.orientation() == QPageLayout::Landscape);
+ printSettings->Set(printing::kSettingMarginsCustom, std::move(marginsDict));
+ printSettings->SetInteger(printing::kSettingMarginsType, printing::CUSTOM_MARGINS);
+
+ printSettings->SetBoolean(printing::kSettingLandscape, pageLayout.orientation() == QPageLayout::Landscape);
+
+ return printSettings;
}
} // namespace
@@ -209,12 +214,11 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, bool
{
if (!pageLayout.isValid())
return false;
- m_printSettings.reset(createPrintSettings());
- m_printSettings->SetInteger(printing::kSettingColor, printInColor ? printing::COLOR : printing::GRAYSCALE);
- applyQPageLayoutSettingsToDictionary(pageLayout, *m_printSettings);
+ m_printSettings.reset(createPrintSettingsFromQPageLayout(pageLayout));
m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds
, web_contents()->GetRenderViewHost()->GetWebkitPreferences().should_print_backgrounds);
+ m_printSettings->SetInteger(printing::kSettingColor, printInColor ? printing::COLOR : printing::GRAYSCALE);
return Send(new PrintMsg_InitiatePrintPreview(routing_id(), false));
}
diff --git a/src/core/proxy_config_service_qt.cpp b/src/core/proxy_config_service_qt.cpp
index 28a36d37f..a6ffb39ab 100644
--- a/src/core/proxy_config_service_qt.cpp
+++ b/src/core/proxy_config_service_qt.cpp
@@ -109,10 +109,13 @@ net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxy
}
m_qtApplicationProxy = qtProxy;
m_qtProxyConfig = net::ProxyConfig();
- if (qtProxy.type() == QNetworkProxy::NoProxy) {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
+ if (qtProxy.type() == QNetworkProxy::NoProxy
+ && QNetworkProxyFactory::usesSystemConfiguration()) {
*config = systemConfig;
return systemAvailability;
}
+#endif
net::ProxyConfig::ProxyRules qtRules;
net::ProxyServer server = fromQNetworkProxy(qtProxy);
diff --git a/src/core/qrc_protocol_handler_qt.cpp b/src/core/qrc_protocol_handler_qt.cpp
index 222961762..eb716f182 100644
--- a/src/core/qrc_protocol_handler_qt.cpp
+++ b/src/core/qrc_protocol_handler_qt.cpp
@@ -46,6 +46,8 @@
namespace QtWebEngineCore {
+const char kQrcSchemeQt[] = "qrc";
+
QrcProtocolHandlerQt::QrcProtocolHandlerQt()
{
}
diff --git a/src/core/qrc_protocol_handler_qt.h b/src/core/qrc_protocol_handler_qt.h
index 53d063810..a2e0cc00b 100644
--- a/src/core/qrc_protocol_handler_qt.h
+++ b/src/core/qrc_protocol_handler_qt.h
@@ -53,6 +53,8 @@ class URLRequestJob;
namespace QtWebEngineCore {
+extern const char kQrcSchemeQt[];
+
// Implements a ProtocolHandler for qrc file jobs. If |network_delegate_| is NULL,
// then all file requests will fail with ERR_ACCESS_DENIED.
class QrcProtocolHandlerQt : public net::URLRequestJobFactory::ProtocolHandler {
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
index a6e35f4be..69f5bfefe 100644
--- a/src/core/renderer/content_renderer_client_qt.cpp
+++ b/src/core/renderer/content_renderer_client_qt.cpp
@@ -135,6 +135,12 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_fr
void ContentRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame* render_frame)
{
+ // Check whether the render_frame has been created and has not been detached yet.
+ // Otherwise the WebFrame is not available.
+ RenderFrameObserverQt *render_frame_observer = RenderFrameObserverQt::Get(render_frame);
+ if (!render_frame_observer || render_frame_observer->isFrameDetached())
+ return; // The frame is invisible to scripts.
+
if (WebChannelIPCTransport *transport = WebChannelIPCTransport::Get(render_frame->GetRenderView()))
transport->RunScriptsAtDocumentStart(render_frame);
UserResourceController::instance()->RunScriptsAtDocumentStart(render_frame);
@@ -142,6 +148,12 @@ void ContentRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame* re
void ContentRendererClientQt::RunScriptsAtDocumentEnd(content::RenderFrame* render_frame)
{
+ // Check whether the render_frame has been created and has not been detached yet.
+ // Otherwise the WebFrame is not available.
+ RenderFrameObserverQt *render_frame_observer = RenderFrameObserverQt::Get(render_frame);
+ if (!render_frame_observer || render_frame_observer->isFrameDetached())
+ return; // The frame is invisible to scripts.
+
UserResourceController::instance()->RunScriptsAtDocumentEnd(render_frame);
}
diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp
index 77bc89f67..53e9407db 100644
--- a/src/core/renderer/render_frame_observer_qt.cpp
+++ b/src/core/renderer/render_frame_observer_qt.cpp
@@ -55,6 +55,8 @@ namespace QtWebEngineCore {
RenderFrameObserverQt::RenderFrameObserverQt(content::RenderFrame* render_frame)
: RenderFrameObserver(render_frame)
+ , RenderFrameObserverTracker<RenderFrameObserverQt>(render_frame)
+ , m_isFrameDetached(false)
{
}
@@ -72,4 +74,14 @@ void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost* ho
}
#endif
+void RenderFrameObserverQt::FrameDetached()
+{
+ m_isFrameDetached = true;
+}
+
+bool RenderFrameObserverQt::isFrameDetached() const
+{
+ return m_isFrameDetached;
+}
+
} // namespace QtWebEngineCore
diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h
index c59b7babc..b74be5cd1 100644
--- a/src/core/renderer/render_frame_observer_qt.h
+++ b/src/core/renderer/render_frame_observer_qt.h
@@ -42,6 +42,7 @@
#include "base/compiler_specific.h"
#include "content/public/renderer/render_frame_observer.h"
+#include "content/public/renderer/render_frame_observer_tracker.h"
namespace content {
@@ -50,7 +51,10 @@ class RenderFrame;
namespace QtWebEngineCore {
-class RenderFrameObserverQt : public content::RenderFrameObserver {
+class RenderFrameObserverQt
+ : public content::RenderFrameObserver
+ , public content::RenderFrameObserverTracker<RenderFrameObserverQt>
+{
public:
explicit RenderFrameObserverQt(content::RenderFrame* render_frame);
~RenderFrameObserverQt();
@@ -59,9 +63,14 @@ public:
void DidCreatePepperPlugin(content::RendererPpapiHost* host) override;
#endif
void OnDestruct() override { }
+ void FrameDetached() override;
+
+ bool isFrameDetached() const;
private:
DISALLOW_COPY_AND_ASSIGN(RenderFrameObserverQt);
+
+ bool m_isFrameDetached;
};
} // namespace QtWebEngineCore
diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp
index 3a44bb182..161d6f493 100644
--- a/src/core/renderer/web_channel_ipc_transport.cpp
+++ b/src/core/renderer/web_channel_ipc_transport.cpp
@@ -164,9 +164,8 @@ void WebChannelIPCTransport::RunScriptsAtDocumentStart(content::RenderFrame *ren
{
// JavaScript run before this point doesn't stick, and needs to be redone.
// ### FIXME: we should try no even installing before
- blink::WebLocalFrame *frame = render_frame->GetWebFrame();
if (m_installed && render_frame->IsMainFrame())
- WebChannelTransport::Install(frame, m_installedWorldId);
+ WebChannelTransport::Install(render_frame->GetWebFrame(), m_installedWorldId);
}
@@ -224,9 +223,12 @@ void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> &
}
v8::Handle<v8::Object> messageObject(v8::Object::New(isolate));
- messageObject->ForceSet(v8::String::NewFromUtf8(isolate, "data")
- , v8::String::NewFromUtf8(isolate, json.constData(), v8::String::kNormalString, json.size())
- , v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ v8::Maybe<bool> wasSet = messageObject->DefineOwnProperty(
+ context,
+ v8::String::NewFromUtf8(isolate, "data"),
+ v8::String::NewFromUtf8(isolate, json.constData(), v8::String::kNormalString, json.size()),
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ Q_ASSERT(!wasSet.IsNothing() && wasSet.FromJust());
v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(onmessageCallbackValue);
const int argc = 1;
diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp
index 61f359a87..bf4661102 100644
--- a/src/core/url_request_context_getter_qt.cpp
+++ b/src/core/url_request_context_getter_qt.cpp
@@ -91,8 +91,6 @@
namespace QtWebEngineCore {
-static const char kQrcSchemeQt[] = "qrc";
-
using content::BrowserThread;
URLRequestContextGetterQt::URLRequestContextGetterQt(QSharedPointer<BrowserContextAdapter> browserContext, content::ProtocolHandlerMap *protocolHandlers, content::URLRequestInterceptorScopedVector request_interceptors)
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index c8d93b3f0..fadbd6d2e 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -351,7 +351,6 @@ WebContentsAdapterPrivate::WebContentsAdapterPrivate()
, adapterClient(0)
, nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd)
, lastFindRequestId(0)
- , currentDropData(nullptr)
, currentDropAction(Qt::IgnoreAction)
, inDragUpdateLoop(false)
, updateDragCursorMessagePollingTimer(new QTimer)
@@ -1114,18 +1113,12 @@ void WebContentsAdapter::setWebChannel(QWebChannel *channel, uint worldId)
static QMimeData *mimeDataFromDropData(const content::DropData &dropData)
{
QMimeData *mimeData = new QMimeData();
- if (!dropData.text.is_null()) {
+ if (!dropData.text.is_null())
mimeData->setText(toQt(dropData.text.string()));
- return mimeData;
- }
- if (!dropData.html.is_null()) {
+ if (!dropData.html.is_null())
mimeData->setHtml(toQt(dropData.html.string()));
- return mimeData;
- }
- if (dropData.url.is_valid()) {
+ if (dropData.url.is_valid())
mimeData->setUrls(QList<QUrl>() << toQt(dropData.url));
- return mimeData;
- }
return mimeData;
}
@@ -1140,15 +1133,14 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD
// Clear certain fields of the drop data to not run into DCHECKs
// of DropDataToWebDragData in render_view_impl.cc.
- content::DropData fixedDropData = dropData;
- fixedDropData.download_metadata.clear();
- fixedDropData.file_contents.clear();
- fixedDropData.file_description_filename.clear();
+ d->currentDropData.reset(new content::DropData(dropData));
+ d->currentDropData->download_metadata.clear();
+ d->currentDropData->file_contents.clear();
+ d->currentDropData->file_description_filename.clear();
d->currentDropAction = Qt::IgnoreAction;
- d->currentDropData = &fixedDropData;
QDrag *drag = new QDrag(dragSource); // will be deleted by Qt's DnD implementation
- drag->setMimeData(mimeDataFromDropData(fixedDropData));
+ drag->setMimeData(mimeDataFromDropData(*d->currentDropData));
if (!pixmap.isNull()) {
drag->setPixmap(pixmap);
drag->setHotSpot(offset);
@@ -1161,7 +1153,7 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD
content::RenderViewHost *rvh = d->webContents->GetRenderViewHost();
rvh->DragSourceSystemDragEnded();
- d->currentDropData = nullptr;
+ d->currentDropData.reset();
}
static blink::WebDragOperationsMask toWeb(const Qt::DropActions action)
@@ -1198,17 +1190,15 @@ void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPoint &screenPos)
{
Q_D(WebContentsAdapter);
- std::unique_ptr<content::DropData> ownedDropData;
- const content::DropData *rvhDropData = d->currentDropData;
- if (!rvhDropData) {
+ if (!d->currentDropData) {
// The drag originated outside the WebEngineView.
- ownedDropData.reset(new content::DropData);
- fillDropDataFromMimeData(ownedDropData.get(), e->mimeData());
- rvhDropData = ownedDropData.get();
+ d->currentDropData.reset(new content::DropData);
+ fillDropDataFromMimeData(d->currentDropData.get(), e->mimeData());
}
content::RenderViewHost *rvh = d->webContents->GetRenderViewHost();
- rvh->DragTargetDragEnter(*rvhDropData, toGfx(e->pos()), toGfx(screenPos),
+ rvh->FilterDropData(d->currentDropData.get());
+ rvh->DragTargetDragEnter(*d->currentDropData, toGfx(e->pos()), toGfx(screenPos),
toWeb(e->possibleActions()),
flagsFromModifiers(e->keyboardModifiers()));
}
@@ -1220,6 +1210,16 @@ Qt::DropAction WebContentsAdapter::updateDragPosition(QDragMoveEvent *e, const Q
rvh->DragTargetDragOver(toGfx(e->pos()), toGfx(screenPos), toWeb(e->possibleActions()),
blink::WebInputEvent::LeftButtonDown);
+ base::MessageLoop *currentMessageLoop = base::MessageLoop::current();
+ DCHECK(currentMessageLoop);
+ if (!currentMessageLoop->NestableTasksAllowed()) {
+ // We're already inside a MessageLoop::RunTask call, and scheduled tasks will not be
+ // executed. That means, updateDragAction will never be called, and the RunLoop below will
+ // remain blocked forever.
+ qWarning("WebContentsAdapter::updateDragPosition called from MessageLoop::RunTask.");
+ return Qt::IgnoreAction;
+ }
+
// Wait until we get notified via RenderViewHostDelegateView::UpdateDragCursor. This calls
// WebContentsAdapter::updateDragAction that will eventually quit the nested loop.
base::RunLoop loop;
@@ -1254,7 +1254,9 @@ void WebContentsAdapter::endDragging(const QPoint &clientPos, const QPoint &scre
Q_D(WebContentsAdapter);
finishDragUpdate();
content::RenderViewHost *rvh = d->webContents->GetRenderViewHost();
+ rvh->FilterDropData(d->currentDropData.get());
rvh->DragTargetDrop(*d->currentDropData, toGfx(clientPos), toGfx(screenPos), 0);
+ d->currentDropData.reset();
}
void WebContentsAdapter::leaveDrag()
@@ -1263,6 +1265,7 @@ void WebContentsAdapter::leaveDrag()
finishDragUpdate();
content::RenderViewHost *rvh = d->webContents->GetRenderViewHost();
rvh->DragTargetDragLeave();
+ d->currentDropData.reset();
}
void WebContentsAdapter::initUpdateDragCursorMessagePollingTimer()
diff --git a/src/core/web_contents_adapter_p.h b/src/core/web_contents_adapter_p.h
index 77522d299..23a1aaef4 100644
--- a/src/core/web_contents_adapter_p.h
+++ b/src/core/web_contents_adapter_p.h
@@ -92,7 +92,7 @@ public:
WebContentsAdapterClient *adapterClient;
quint64 nextRequestId;
int lastFindRequestId;
- const content::DropData *currentDropData;
+ std::unique_ptr<content::DropData> currentDropData;
Qt::DropAction currentDropAction;
bool inDragUpdateLoop;
base::Closure dragUpdateLoopQuitClosure;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 9d0965818..36acfe62e 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -74,6 +74,7 @@
#include "ui/events/latency_info.h"
#include <QDesktopServices>
+#include <QTimer>
namespace QtWebEngineCore {
@@ -107,13 +108,19 @@ content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents
Q_ASSERT(target);
content::NavigationController::LoadURLParams load_url_params(params.url);
+ load_url_params.source_site_instance = params.source_site_instance;
load_url_params.referrer = params.referrer;
load_url_params.frame_tree_node_id = params.frame_tree_node_id;
+ load_url_params.redirect_chain = params.redirect_chain;
load_url_params.transition_type = params.transition;
load_url_params.extra_headers = params.extra_headers;
load_url_params.should_replace_current_entry = params.should_replace_current_entry;
load_url_params.is_renderer_initiated = params.is_renderer_initiated;
load_url_params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
+ if (params.uses_post) {
+ load_url_params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
+ load_url_params.post_data = params.post_data;
+ }
target->GetController().LoadURLWithParams(load_url_params);
return target;
@@ -320,7 +327,11 @@ void WebContentsDelegateQt::RunFileChooser(content::RenderFrameHost *frameHost,
m_filePickerController.reset(new FilePickerController(static_cast<FilePickerController::FileChooserMode>(params.mode),
web_contents(), toQt(params.default_file_name.value()), acceptedMimeTypes));
- m_viewClient->runFileChooser(m_filePickerController);
+
+ // Defer the call to not block base::MessageLoop::RunTask with modal dialogs.
+ QTimer::singleShot(0, [this] () {
+ m_viewClient->runFileChooser(m_filePickerController);
+ });
}
bool WebContentsDelegateQt::AddMessageToConsole(content::WebContents *source, int32_t level, const base::string16 &message, int32_t line_no, const base::string16 &source_id)
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index 7fe8fb612..491835e45 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -309,8 +309,10 @@ WebEngineContext::WebEngineContext()
if (useEmbeddedSwitches) {
// Inspired by the Android port's default switches
- parsedCommandLine->AppendSwitch(switches::kEnableOverlayScrollbar);
- parsedCommandLine->AppendSwitch(switches::kEnablePinch);
+ if (!parsedCommandLine->HasSwitch(switches::kDisableOverlayScrollbar))
+ parsedCommandLine->AppendSwitch(switches::kEnableOverlayScrollbar);
+ if (!parsedCommandLine->HasSwitch(switches::kDisablePinch))
+ parsedCommandLine->AppendSwitch(switches::kEnablePinch);
parsedCommandLine->AppendSwitch(switches::kEnableViewport);
parsedCommandLine->AppendSwitch(switches::kMainFrameResizesAreOrientationChanges);
parsedCommandLine->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
@@ -325,7 +327,7 @@ WebEngineContext::WebEngineContext()
const char *glType = 0;
#ifndef QT_NO_OPENGL
if (!usingANGLE() && !usingSoftwareDynamicGL() && !usingQtQuick2DRenderer()) {
- if (qt_gl_global_share_context()) {
+ if (qt_gl_global_share_context() && qt_gl_global_share_context()->isValid()) {
if (!strcmp(qt_gl_global_share_context()->nativeHandle().typeName(), "QEGLNativeContext")) {
if (qt_gl_global_share_context()->isOpenGLES()) {
glType = gl::kGLImplementationEGLName;
@@ -359,16 +361,7 @@ WebEngineContext::WebEngineContext()
glType = gl::kGLImplementationDesktopName;
}
} else {
- qWarning("WebEngineContext used before QtWebEngine::initialize()");
- // We have to assume the default OpenGL module type will be used.
- switch (QOpenGLContext::openGLModuleType()) {
- case QOpenGLContext::LibGL:
- glType = gl::kGLImplementationDesktopName;
- break;
- case QOpenGLContext::LibGLES:
- glType = gl::kGLImplementationEGLName;
- break;
- }
+ qWarning("WebEngineContext used before QtWebEngine::initialize() or OpenGL context creation failed.");
}
}
#endif
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index 2be59d1c6..40977812d 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -69,7 +69,7 @@ QString fallbackDir() {
return directory;
}
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
static inline CFBundleRef frameworkBundle()
{
return CFBundleGetBundleWithIdentifier(CFSTR("org.qt-project.Qt.QtWebEngineCore"));
@@ -112,6 +112,34 @@ static QString getResourcesPath(CFBundleRef frameworkBundle)
}
#endif
+#if defined(OS_MACOSX)
+static QString getMainApplicationResourcesPath()
+{
+ QString resourcesPath;
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ if (!mainBundle)
+ return resourcesPath;
+
+ // Will point to Resources inside an app bundle, or in case if the application is not packaged
+ // as a bundle, will point to the application directory, where the resources are assumed to be
+ // found.
+ CFURLRef resourcesRelativeUrl = CFBundleCopyResourcesDirectoryURL(mainBundle);
+ if (!resourcesRelativeUrl)
+ return resourcesPath;
+
+ CFURLRef resourcesAbsoluteUrl = CFURLCopyAbsoluteURL(resourcesRelativeUrl);
+ CFStringRef resourcesAbolutePath = CFURLCopyFileSystemPath(resourcesAbsoluteUrl,
+ kCFURLPOSIXPathStyle);
+ resourcesPath = QString::fromCFString(resourcesAbolutePath);
+ CFRelease(resourcesAbolutePath);
+ CFRelease(resourcesAbsoluteUrl);
+ CFRelease(resourcesRelativeUrl);
+
+ return resourcesPath;
+}
+
+#endif
+
QString subProcessPath()
{
static QString processPath;
@@ -181,18 +209,42 @@ QString localesPath()
#if defined(ENABLE_SPELLCHECK)
QString dictionariesPath()
{
+ static QString potentialDictionariesPath;
+ static bool initialized = false;
+ QStringList candidatePaths;
+ if (!initialized) {
+ initialized = true;
+
+ // First try to find dictionaries near the application.
+#ifdef OS_MACOSX
+ QString resourcesDictionariesPath = getMainApplicationResourcesPath()
+ % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
+ candidatePaths << resourcesDictionariesPath;
+#endif
+ QString applicationDictionariesPath = QCoreApplication::applicationDirPath()
+ % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
+ candidatePaths << applicationDictionariesPath;
+
+ // Then try to find dictionaries near the installed library.
#if defined(OS_MACOSX) && defined(QT_MAC_FRAMEWORK_BUILD)
- return getResourcesPath(frameworkBundle()) % QLatin1String("/qtwebengine_dictionaries");
-#else
- // first local path
- static QString potentialDictionariesPath = QCoreApplication::applicationDirPath() % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
+ QString frameworkDictionariesPath = getResourcesPath(frameworkBundle())
+ % QLatin1String("/qtwebengine_dictionaries");
+ candidatePaths << frameworkDictionariesPath;
+#endif
+
+ QString libraryDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath)
+ % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
+ candidatePaths << libraryDictionariesPath;
- // now global one
- if (!QFileInfo::exists(potentialDictionariesPath))
- potentialDictionariesPath = QLibraryInfo::location(QLibraryInfo::DataPath) % QDir::separator() % QLatin1String("qtwebengine_dictionaries");
+ Q_FOREACH (const QString &candidate, candidatePaths) {
+ if (QFileInfo::exists(candidate)) {
+ potentialDictionariesPath = candidate;
+ break;
+ }
+ }
+ }
return potentialDictionariesPath;
-#endif
}
#endif // ENABLE_SPELLCHECK
diff --git a/src/src.pro b/src/src.pro
index dc6bc5274..9b5373181 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -14,8 +14,7 @@ SUBDIRS += core \
plugins
# allow only desktop builds of qwebengine_convert_dict
-# osx does not use hunspell
-!contains(WEBENGINE_CONFIG, no_spellcheck):!osx:!cross_compile {
+contains(WEBENGINE_CONFIG, use_spellchecker):!contains(WEBENGINE_CONFIG, use_native_spellchecker):!cross_compile {
SUBDIRS += qwebengine_convert_dict
qwebengine_convert_dict.subdir = tools/qwebengine_convert_dict
qwebengine_convert_dict.depends = core
diff --git a/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro
index 1781b843d..715081b5f 100644
--- a/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro
+++ b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro
@@ -1,10 +1,11 @@
option(host_build)
# Look for linking information produced by gyp for our target according to core_generated.gyp
-!include($$OUT_PWD/../../core/$$getConfigDir()/QtWebEngineCore_linking.pri) {
+!include($$OUT_PWD/../../core/$$getConfigDir()/convert_dict_linking.pri) {
error("Could not find the linking information that gyp should have generated.")
}
-# remove object files from linking information
+
+# skip dummy main.cpp file
OBJECTS =
# Fixme: -Werror=unused-parameter in core
diff --git a/src/webengine/api/qquickwebenginedialogrequests.cpp b/src/webengine/api/qquickwebenginedialogrequests.cpp
index 7cb4953fc..641793e12 100644
--- a/src/webengine/api/qquickwebenginedialogrequests.cpp
+++ b/src/webengine/api/qquickwebenginedialogrequests.cpp
@@ -735,15 +735,15 @@ void QQuickWebEngineFileDialogRequest::dialogReject()
onFormValidationMessageRequested: function(request) {
request.accepted = true;
switch (request.type) {
- case FormValidationMessageRequest.RequestTypeShow:
+ case FormValidationMessageRequest.Show:
validationMessage.text = request.text;
validationMessage.x = request.x;
validationMessage.y = request.y
validationMessage.visible = true;
break;
- case FormValidationMessageRequest.RequestTypeMove:
+ case FormValidationMessageRequest.Move:
break;
- case FormValidationMessageRequest.RequestTypeHide:
+ case FormValidationMessageRequest.Hide:
validationMessage.visible = false;
break;
}
@@ -816,11 +816,11 @@ QString QQuickWebEngineFormValidationMessageRequest::subText() const
The type of the form validation message request.
- \value ValidationMessageRequest.RequestTypeShow
+ \value ValidationMessageRequest.Show
The form validation message should be shown.
- \value ValidationMessageRequest.RequestTypeHide
+ \value ValidationMessageRequest.Hide
The form validation message should be hidden.
- \value ValidationMessageRequest.RequestTypeMove
+ \value ValidationMessageRequest.Move
The form validation message should be moved.
*/
diff --git a/src/webengine/api/qquickwebenginedialogrequests_p.h b/src/webengine/api/qquickwebenginedialogrequests_p.h
index d1ddc6607..d8a0e004c 100644
--- a/src/webengine/api/qquickwebenginedialogrequests_p.h
+++ b/src/webengine/api/qquickwebenginedialogrequests_p.h
@@ -228,9 +228,9 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineFormValidationMessageRequest : p
Q_OBJECT
public:
enum RequestType {
- RequestTypeShow,
- RequestTypeHide,
- RequestTypeMove,
+ Show,
+ Hide,
+ Move,
};
Q_ENUM(RequestType)
Q_PROPERTY(QRect anchor READ anchor CONSTANT FINAL)
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index 1ca97adea..871428f33 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -87,8 +87,8 @@ ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::MimeHtmlSaveFormat, QtWebEngineC
register custom URL schemes (QQuickWebEngineProfile::installUrlSchemeHandler).
Spellchecking HTML form fields can be enabled per profile by setting the \l spellCheckEnabled
- property and the current language used for spellchecking can be set by using the
- \l spellCheckLanguage property.
+ property and the current languages used for spellchecking can be set by using the
+ \l spellCheckLanguages property.
*/
/*!
@@ -618,27 +618,47 @@ QQuickWebEngineProfile *QQuickWebEngineProfile::defaultProfile()
}
/*!
- \property QQuickWebEngineProfile::spellCheckLanguage
- \brief the language used by the spell checker.
+ \property QQuickWebEngineProfile::spellCheckLanguages
+ \brief The languages used by the spell checker.
\since QtWebEngine 1.4
*/
/*!
- \qmlproperty QString WebEngineProfile::spellCheckLanguage
+ \qmlproperty list<string> WebEngineProfile::spellCheckLanguages
- This property holds the language used by the spell checker.
- The language should match the name of the \c .bdic dictionary.
- For example, the \a language \c en-US will load the \c en-US.bdic
+ This property holds the list of languages used by the spell checker.
+ Each language should match the name of the \c .bdic dictionary.
+ For example, the language \c en-US will load the \c en-US.bdic
dictionary file.
- The web engine checks for the \c qtwebengine_dictionaries subdirectory
- first in the local directory and if it is not found in the Qt
- installation directory:
+ Qt WebEngine checks for the \c qtwebengine_dictionaries subdirectory
+ first in the local directory and if it is not found, in the Qt
+ installation directory.
+
+ On macOS, depending on how Qt WebEngine is configured at build time, there are two possibilities
+ how spellchecking data is found:
+
+ \list
+ \li Hunspell dictionaries (default) - .bdic dictionaries are used, just like on other
+ platforms
+ \li Native dictionaries - the macOS spellchecking APIs are used (which means the results
+ will depend on the installed OS dictionaries)
+ \endlist
+
+ Thus, in the macOS Hunspell case, Qt WebEngine will look in the \e qtwebengine_dictionaries
+ subdirectory located inside the application bundle \c Resources directory, and also in the
+ \c Resources directory located inside the Qt framework bundle.
+
+ To summarize, in case of Hunspell usage, the following paths are considered:
\list
\li QCoreApplication::applicationDirPath()/qtwebengine_dictionaries
+ or QCoreApplication::applicationDirPath()/../Contents/Resources/qtwebengine_dictionaries
+ (on macOS)
\li [QLibraryInfo::DataPath]/qtwebengine_dictionaries
+ or path/to/QtWebEngineCore.framework/Resources/qtwebengine_dictionaries (Qt framework
+ bundle on macOS)
\endlist
For more information about how to compile \c .bdic dictionaries, see the
@@ -646,24 +666,24 @@ QQuickWebEngineProfile *QQuickWebEngineProfile::defaultProfile()
\since QtWebEngine 1.4
*/
-void QQuickWebEngineProfile::setSpellCheckLanguage(const QString &language)
+void QQuickWebEngineProfile::setSpellCheckLanguages(const QStringList &languages)
{
Q_D(QQuickWebEngineProfile);
- if (language != d->browserContext()->spellCheckLanguage()) {
- d->browserContext()->setSpellCheckLanguage(language);
- emit spellCheckLanguageChanged();
+ if (languages != d->browserContext()->spellCheckLanguages()) {
+ d->browserContext()->setSpellCheckLanguages(languages);
+ emit spellCheckLanguagesChanged();
}
}
/*!
\since 5.8
- Returns the language used by the spell checker.
+ Returns the list of languages used by the spell checker.
*/
-QString QQuickWebEngineProfile::spellCheckLanguage() const
+QStringList QQuickWebEngineProfile::spellCheckLanguages() const
{
const Q_D(QQuickWebEngineProfile);
- return d->browserContext()->spellCheckLanguage();
+ return d->browserContext()->spellCheckLanguages();
}
/*!
@@ -674,7 +694,7 @@ QString QQuickWebEngineProfile::spellCheckLanguage() const
*/
/*!
- \qmlproperty QString WebEngineProfile::spellCheckEnabled
+ \qmlproperty bool WebEngineProfile::spellCheckEnabled
This property holds whether the web engine spell checker is enabled.
diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h
index 577cc7f6a..d0d925930 100644
--- a/src/webengine/api/qquickwebengineprofile.h
+++ b/src/webengine/api/qquickwebengineprofile.h
@@ -71,7 +71,7 @@ class Q_WEBENGINE_EXPORT QQuickWebEngineProfile : public QObject {
Q_PROPERTY(QString httpAcceptLanguage READ httpAcceptLanguage WRITE setHttpAcceptLanguage NOTIFY httpAcceptLanguageChanged FINAL REVISION 1)
Q_PROPERTY(PersistentCookiesPolicy persistentCookiesPolicy READ persistentCookiesPolicy WRITE setPersistentCookiesPolicy NOTIFY persistentCookiesPolicyChanged FINAL)
Q_PROPERTY(int httpCacheMaximumSize READ httpCacheMaximumSize WRITE setHttpCacheMaximumSize NOTIFY httpCacheMaximumSizeChanged FINAL)
- Q_PROPERTY(QString spellCheckLanguage READ spellCheckLanguage WRITE setSpellCheckLanguage NOTIFY spellCheckLanguageChanged FINAL REVISION 3)
+ Q_PROPERTY(QStringList spellCheckLanguages READ spellCheckLanguages WRITE setSpellCheckLanguages NOTIFY spellCheckLanguagesChanged FINAL REVISION 3)
Q_PROPERTY(bool spellCheckEnabled READ isSpellCheckEnabled WRITE setSpellCheckEnabled NOTIFY spellCheckEnabledChanged FINAL REVISION 3)
public:
@@ -131,8 +131,8 @@ public:
Q_REVISION(2) Q_INVOKABLE void clearHttpCache();
- void setSpellCheckLanguage(const QString &language);
- QString spellCheckLanguage() const;
+ void setSpellCheckLanguages(const QStringList &languages);
+ QStringList spellCheckLanguages() const;
void setSpellCheckEnabled(bool enabled);
bool isSpellCheckEnabled() const;
@@ -148,7 +148,7 @@ Q_SIGNALS:
void persistentCookiesPolicyChanged();
void httpCacheMaximumSizeChanged();
Q_REVISION(1) void httpAcceptLanguageChanged();
- Q_REVISION(3) void spellCheckLanguageChanged();
+ Q_REVISION(3) void spellCheckLanguagesChanged();
Q_REVISION(3) void spellCheckEnabledChanged();
void downloadRequested(QQuickWebEngineDownloadItem *download);
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index 61f940f15..6ca9954cf 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -1109,7 +1109,7 @@ void QQuickWebEngineViewPrivate::showValidationMessage(const QRect &anchor, cons
#endif
Q_Q(QQuickWebEngineView);
QQuickWebEngineFormValidationMessageRequest *request;
- request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::RequestTypeShow,
+ request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::Show,
anchor,mainText,subText);
// mark the object for gc by creating temporary jsvalue
qmlEngine(q)->newQObject(request);
@@ -1122,7 +1122,7 @@ void QQuickWebEngineViewPrivate::hideValidationMessage()
{
Q_Q(QQuickWebEngineView);
QQuickWebEngineFormValidationMessageRequest *request;
- request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::RequestTypeHide);
+ request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::Hide);
// mark the object for gc by creating temporary jsvalue
qmlEngine(q)->newQObject(request);
Q_EMIT q->formValidationMessageRequested(request);
@@ -1134,7 +1134,7 @@ void QQuickWebEngineViewPrivate::moveValidationMessage(const QRect &anchor)
{
Q_Q(QQuickWebEngineView);
QQuickWebEngineFormValidationMessageRequest *request;
- request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::RequestTypeMove,
+ request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::Move,
anchor);
// mark the object for gc by creating temporary jsvalue
qmlEngine(q)->newQObject(request);
diff --git a/src/webengine/doc/qtwebengine.qdocconf b/src/webengine/doc/qtwebengine.qdocconf
index d9b1f1154..fe83b082f 100644
--- a/src/webengine/doc/qtwebengine.qdocconf
+++ b/src/webengine/doc/qtwebengine.qdocconf
@@ -18,9 +18,9 @@ qhp.QtWebEngine.customFilters.Qt.filterAttributes = qtwebengine $QT_VERSION
qhp.QtWebEngine.subprojects = classes qmltypes examples
-qhp.QtWebEngine.subprojects.classes.title = C++ Classes
-qhp.QtWebEngine.subprojects.classes.indexTitle = Qt WebEngine C++ Classes
-qhp.QtWebEngine.subprojects.classes.selectors = class doc:headerfile
+qhp.QtWebEngine.subprojects.classes.title = C++ Classes and Namespaces
+qhp.QtWebEngine.subprojects.classes.indexTitle = Qt WebEngine C++ Classes and Namespaces
+qhp.QtWebEngine.subprojects.classes.selectors = class group:qtwebengine-namespaces doc:headerfile
qhp.QtWebEngine.subprojects.classes.sortPages = true
qhp.QtWebEngine.subprojects.qmltypes.title = QML Types
diff --git a/src/webengine/doc/snippets/qtwebengine_build_snippet.qdoc b/src/webengine/doc/snippets/qtwebengine_build_snippet.qdoc
new file mode 100644
index 000000000..248296588
--- /dev/null
+++ b/src/webengine/doc/snippets/qtwebengine_build_snippet.qdoc
@@ -0,0 +1,8 @@
+//! [0]
+QT += webengine
+//! [0]
+
+
+//! [1]
+#include <QtWebEngine>
+//! [1]
diff --git a/src/webengine/doc/src/qtwebengine-deploying.qdoc b/src/webengine/doc/src/qtwebengine-deploying.qdoc
index b6b91f2e9..25b6d218c 100644
--- a/src/webengine/doc/src/qtwebengine-deploying.qdoc
+++ b/src/webengine/doc/src/qtwebengine-deploying.qdoc
@@ -30,7 +30,7 @@
\title Deploying Qt WebEngine Applications
The way to package and deploy applications varies between operating systems.
- For Windows and macOS, \l{The Windows Deployment Tool}{windeployqt} and
+ For Windows and \macos, \l{The Windows Deployment Tool}{windeployqt} and
\l{Deploying Applications on OS X}{macdeployqt} automate the steps to
generate a stand-alone application package.
@@ -47,7 +47,7 @@
limitations are:
\list
- \li Qt WebEngine currently supports only Windows, Linux, and macOS.
+ \li Qt WebEngine currently supports only Windows, Linux, and \macos.
\li On Windows, Qt WebEngine only supports Windows Vista or newer as
target platform. Due to use of newer API in Chromium, Windows XP is
@@ -102,7 +102,7 @@
For Qt installations, this is \c QTDIR/libexec (Linux) or \c QTDIR\bin
(Windows). The path can be changed by defining a \c qt.conf file, for
example. Alternatively, an executable path can be set as a value of the
- \c QTWEBENGINEPROCESS_PATH environment variable. On macOS, Qt WebEngine
+ \c QTWEBENGINEPROCESS_PATH environment variable. On \macos, Qt WebEngine
looks for the executable in \c .app/Helpers/QtWebEngineProcess.
\section2 Deploying Resources
@@ -128,7 +128,7 @@
\list
\li On Linux and Windows: the \c resources directory in the directory
specified by QLibraryInfo::location(QLibraryInfo::DataPath)
- \li On macOS: \c .app/Content/Resources
+ \li On \macos: \c .app/Content/Resources
\endlist
\section2 Translations
@@ -136,7 +136,7 @@
Locale data (such as \c en-US.pak) is searched form the following locations:
\list
- \li On macOS: \c .app/Content/Resources
+ \li On \macos: \c .app/Content/Resources
\li On Linux and Windows: \c qtwebengine_locales directory in the
directory specified by
QLibraryInfo::location(QLibraryInfo::TranslationsPath)
diff --git a/src/webengine/doc/src/qtwebengine-features.qdoc b/src/webengine/doc/src/qtwebengine-features.qdoc
index 5ba3f23b8..647f1030b 100644
--- a/src/webengine/doc/src/qtwebengine-features.qdoc
+++ b/src/webengine/doc/src/qtwebengine-features.qdoc
@@ -222,6 +222,7 @@
\li Linux
\code
/usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so
+ /usr/lib/adobe-flashplugin/libpepflashplayer.so
/usr/lib/PepperFlash/libpepflashplayer.so
/usr/lib64/chromium/PepperFlash/libpepflashplayer.so
\endcode
@@ -292,9 +293,9 @@
{WebEngineProfile.spellCheckEnabled} property in Qt Quick applications.
The current language used for spellchecking is defined per profile, and can
- be set using the QWebEngineProfile::setSpellCheckLanguage() method or the
- \l {QQuickWebEngineProfile::spellCheckLanguage}
- {WebEngineProfile.spellCheckLanguage} property.
+ be set using the QWebEngineProfile::setSpellCheckLanguages() method or the
+ \l {QQuickWebEngineProfile::spellCheckLanguages}
+ {WebEngineProfile.spellCheckLanguages} property.
This feature can be tested by building and running the
\l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}.
diff --git a/src/webengine/doc/src/qtwebengine-index.qdoc b/src/webengine/doc/src/qtwebengine-index.qdoc
index c4be591ff..bd6cc9a32 100644
--- a/src/webengine/doc/src/qtwebengine-index.qdoc
+++ b/src/webengine/doc/src/qtwebengine-index.qdoc
@@ -28,7 +28,6 @@
/*!
\page qtwebengine-index.html
\title Qt WebEngine
- \ingroup modules
\brief Provides functionality for rendering regions of dynamic web content.
diff --git a/src/webengine/doc/src/qtwebengine-module.qdoc b/src/webengine/doc/src/qtwebengine-module.qdoc
new file mode 100644
index 000000000..97657f6a9
--- /dev/null
+++ b/src/webengine/doc/src/qtwebengine-module.qdoc
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \module QtWebEngine
+ \title Qt WebEngine C++ Classes
+ \brief Exposes C++ functionality to Qt Quick.
+ \ingroup modules
+
+ The Qt WebEngine module exposes C++ functionality to Qt Quick.
+
+ To include the definitions of the module's classes, use the
+ following directive:
+
+ \snippet qtwebengine_build_snippet.qdoc 1
+
+ To link against the module, add the following to your qmake project file:
+
+ \snippet qtwebengine_build_snippet.qdoc 0
+*/
diff --git a/src/webengine/doc/src/qtwebengine-overview.qdoc b/src/webengine/doc/src/qtwebengine-overview.qdoc
index d5b7d40a0..6995be2fa 100644
--- a/src/webengine/doc/src/qtwebengine-overview.qdoc
+++ b/src/webengine/doc/src/qtwebengine-overview.qdoc
@@ -197,9 +197,11 @@
\section1 Proxy Support
- If QNetworkProxy::applicationProxy is set, it will also be used for Qt WebEngine. Otherwise,
- Qt WebEngine automatically picks up the proxy configuration from OS X and Windows. On Linux,
- it acknowledges settings from KDE and Gnome.
+ Qt WebEngine uses the proxy settings from \l{Qt Network}. If
+ QNetworkProxy::applicationProxy is set, it will also be used for Qt WebEngine, and if
+ QNetworkProxy::usesSystemConfiguration() is enabled, the proxy settings are automatically
+ retrieved from the system. Settings from an installed QNetworkProxyFactory will be ignored
+ though.
If a proxy requires authentication, QWebEnginePage::proxyAuthenticationRequired is emitted.
For Qt Quick, a dialog is shown.
@@ -248,7 +250,7 @@
\section1 Platform Notes
- Qt WebEngine currently supports only Windows, Linux, and OS X. Due to Chromium build
+ Qt WebEngine currently supports only Windows, Linux, and \macos. Due to Chromium build
requirements it also often requires a newer compiler than the rest of Qt. See
\l{Qt WebEngine Platform Notes} for further details.
diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
index 9a59f1f1f..c5ebe0f06 100644
--- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
+++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
@@ -41,7 +41,7 @@
\list
\li \l{Qt for Windows - Requirements}
\li \l{Qt for X11 Requirements}
- \li \l{Qt for OS X - Requirements}
+ \li \l{Qt for macOS - Requirements}
\endlist
In addition, the following tools are required for building the \l {Qt WebEngine} module:
@@ -50,7 +50,7 @@
\li \l {All Platforms}
\li \l {Windows}
\li \l {Linux}
- \li \l {OS X}
+ \li \l {macOS}
\endlist
The tests for skipping the Qt WebEngine build are located in the
@@ -99,22 +99,22 @@
Further, development packages for \c khr and \c libcap need to be installed.
- \section2 OS X
+ \section2 \macos
- On OS X, the following are required:
+ On \macos, the following are required:
\list
- \li OS X 10.10 or later
- \li Xcode 6.3 or later
- \li OS X 10.10 SDK or later
+ \li \macos 10.9 or later
+ \li Xcode 5.1 or later
+ \li \macos 10.10 SDK or later
\endlist
- \note Qt WebEngine cannot be built for the 32-bit mode of OS X (using the
+ \note Qt WebEngine cannot be built for the 32-bit mode of \macos (using the
\c macx-clang-32 \c mkspec).
\section1 Mac App Store Compatibility
- By default, Qt WebEngine uses private OS X API, which might cause an application to be
+ By default, Qt WebEngine uses private \macos API, which might cause an application to be
rejected when submitted to the Mac App Store. To configure Qt WebEngine not to use these API
calls, Qt WebEngine has to be recompiled:
@@ -125,10 +125,10 @@
However, this will cause some behavioral changes, such as:
\list
- \li The OS X Kill Ring functionality will no longer work (emacs-like copy pasting).
+ \li The \macos Kill Ring functionality will no longer work (emacs-like copy pasting).
\li Certain Chromium sandboxing cleanup is not done.
\li Text areas will be painted with a different style.
- \li Text fields might be painted with a different style on Mountain Lion (OS X 10.8).
+ \li Text fields might be painted with a different style on Mountain Lion (\macos 10.8).
\endlist
\section1 Default QSurfaceFormat OpenGL Profile Support
@@ -137,7 +137,7 @@
before the application instance is declared, to make sure that all created OpenGL contexts use
the same OpenGL profile.
- On OS X, if the default QSurfaceFormat is set after the application instance, the application
+ On \macos, if the default QSurfaceFormat is set after the application instance, the application
will exit with qFatal(), and print a message that the default QSurfaceFormat should be set
before the application instance.
*/
diff --git a/src/webengine/doc/src/qwebengine-licensing.qdoc b/src/webengine/doc/src/qwebengine-licensing.qdoc
index c31bd9dac..a7642df5a 100644
--- a/src/webengine/doc/src/qwebengine-licensing.qdoc
+++ b/src/webengine/doc/src/qwebengine-licensing.qdoc
@@ -17,7 +17,7 @@ Third party licenses included in the sources are:
/*!
\contentspage qtwebengine-licensing.html
-\page qtwebengine-3rdparty-chromium-global.html
+\page qtwebengine-3rdparty-chromium-global.html attribution
\ingroup qtwebengine-licensing
\title Chromium License
\brief BSD
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index e9312a92a..0fd2087d4 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -66,7 +66,7 @@ class QtWebEnginePlugin : public QQmlExtensionPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
- virtual void initializeEngine(QQmlEngine *engine, const char *uri)
+ virtual void initializeEngine(QQmlEngine *engine, const char *uri) Q_DECL_OVERRIDE
{
Q_UNUSED(uri);
engine->addImageProvider(QQuickWebEngineFaviconProvider::identifier(), new QQuickWebEngineFaviconProvider);
@@ -77,8 +77,8 @@ public:
Q_ASSERT(QLatin1String(uri) == QLatin1String("QtWebEngine"));
qmlRegisterType<QQuickWebEngineView>(uri, 1, 0, "WebEngineView");
- qmlRegisterUncreatableType<QQuickWebEngineLoadRequest>(uri, 1, 0, "WebEngineLoadRequest", tr("Cannot create separate instance of WebEngineLoadRequest"));
- qmlRegisterUncreatableType<QQuickWebEngineNavigationRequest>(uri, 1, 0, "WebEngineNavigationRequest", tr("Cannot create separate instance of WebEngineNavigationRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineLoadRequest>(uri, 1, 0, "WebEngineLoadRequest", msgUncreatableType("WebEngineLoadRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineNavigationRequest>(uri, 1, 0, "WebEngineNavigationRequest", msgUncreatableType("WebEngineNavigationRequest"));
qmlRegisterType<QQuickWebEngineView, 1>(uri, 1, 1, "WebEngineView");
qmlRegisterType<QQuickWebEngineView, 2>(uri, 1, 2, "WebEngineView");
@@ -89,7 +89,7 @@ public:
qmlRegisterType<QQuickWebEngineProfile, 2>(uri, 1, 3, "WebEngineProfile");
qmlRegisterType<QQuickWebEngineProfile, 3>(uri, 1, 4, "WebEngineProfile");
qmlRegisterType<QQuickWebEngineScript>(uri, 1, 1, "WebEngineScript");
- qmlRegisterUncreatableType<QQuickWebEngineCertificateError>(uri, 1, 1, "WebEngineCertificateError", tr("Cannot create separate instance of WebEngineCertificateError"));
+ qmlRegisterUncreatableType<QQuickWebEngineCertificateError>(uri, 1, 1, "WebEngineCertificateError", msgUncreatableType("WebEngineCertificateError"));
qmlRegisterUncreatableType<QQuickWebEngineDownloadItem>(uri, 1, 1, "WebEngineDownloadItem",
tr("Cannot create a separate instance of WebEngineDownloadItem"));
qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 1>(uri, 1, 2, "WebEngineDownloadItem",
@@ -98,7 +98,7 @@ public:
tr("Cannot create a separate instance of WebEngineDownloadItem"));
qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 3>(uri, 1, 4, "WebEngineDownloadItem",
tr("Cannot create a separate instance of WebEngineDownloadItem"));
- qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 1, "WebEngineNewViewRequest", tr("Cannot create separate instance of WebEngineNewViewRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 1, "WebEngineNewViewRequest", msgUncreatableType("WebEngineNewViewRequest"));
qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 1, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
qmlRegisterUncreatableType<QQuickWebEngineSettings, 1>(uri, 1, 2, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
qmlRegisterUncreatableType<QQuickWebEngineSettings, 2>(uri, 1, 3, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
@@ -112,21 +112,27 @@ public:
tr("Cannot create a separate instance of FullScreenRequest"));
qmlRegisterUncreatableType<QQuickWebEngineContextMenuRequest>(uri, 1, 4, "ContextMenuRequest",
- tr("Cannot create separate instance of ContextMenuRequest"));
+ msgUncreatableType("ContextMenuRequest"));
qmlRegisterUncreatableType<QQuickWebEngineAuthenticationDialogRequest>(uri, 1, 4, "AuthenticationDialogRequest",
- tr("Cannot create separate instance of AuthenticationDialogRequest"));
+ msgUncreatableType("AuthenticationDialogRequest"));
qmlRegisterUncreatableType<QQuickWebEngineJavaScriptDialogRequest>(uri, 1, 4, "JavaScriptDialogRequest",
- tr("Cannot create separate instance of JavaScriptDialogRequest"));
+ msgUncreatableType("JavaScriptDialogRequest"));
qmlRegisterUncreatableType<QQuickWebEngineColorDialogRequest>(uri, 1, 4, "ColorDialogRequest",
- tr("Cannot create separate instance of ColorDialogRequest"));
+ msgUncreatableType("ColorDialogRequest"));
qmlRegisterUncreatableType<QQuickWebEngineFileDialogRequest>(uri, 1, 4, "FileDialogRequest",
- tr("Cannot create separate instance of FileDialogRequest"));
+ msgUncreatableType("FileDialogRequest"));
qmlRegisterUncreatableType<QQuickWebEngineFormValidationMessageRequest>(uri, 1, 4, "FormValidationMessageRequest",
- tr("Cannot create separate instance of FormValidationMessageRequest"));
+ msgUncreatableType("FormValidationMessageRequest"));
// For now (1.x import), the latest revision matches the minor version of the import.
qmlRegisterRevision<QQuickWebEngineView, LATEST_WEBENGINEVIEW_REVISION>(uri, 1, LATEST_WEBENGINEVIEW_REVISION);
}
+
+private:
+ static QString msgUncreatableType(const char *className)
+ {
+ return tr("Cannot create separate instance of %1").arg(QLatin1String(className));
+ }
};
QT_END_NAMESPACE
diff --git a/src/webengine/plugin/plugins.qmltypes b/src/webengine/plugin/plugins.qmltypes
index c8aaaf420..48a572866 100644
--- a/src/webengine/plugin/plugins.qmltypes
+++ b/src/webengine/plugin/plugins.qmltypes
@@ -198,9 +198,9 @@ Module {
Enum {
name: "RequestType"
values: {
- "RequestTypeShow": 0,
- "RequestTypeHide": 1,
- "RequestTypeMove": 2
+ "Show": 0,
+ "Hide": 1,
+ "Move": 2
}
}
Property { name: "anchor"; type: "QRect"; isReadonly: true }
@@ -359,10 +359,10 @@ Module {
Property { name: "httpAcceptLanguage"; revision: 1; type: "string" }
Property { name: "persistentCookiesPolicy"; type: "PersistentCookiesPolicy" }
Property { name: "httpCacheMaximumSize"; type: "int" }
- Property { name: "spellCheckLanguage"; revision: 3; type: "string" }
+ Property { name: "spellCheckLanguages"; revision: 3; type: "QStringList" }
Property { name: "spellCheckEnabled"; revision: 3; type: "bool" }
Signal { name: "httpAcceptLanguageChanged"; revision: 1 }
- Signal { name: "spellCheckLanguageChanged"; revision: 3 }
+ Signal { name: "spellCheckLanguagesChanged"; revision: 3 }
Signal { name: "spellCheckEnabledChanged"; revision: 3 }
Signal {
name: "downloadRequested"
diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp
index 6896b850d..a37484023 100644
--- a/src/webengine/ui_delegates_manager.cpp
+++ b/src/webengine/ui_delegates_manager.cpp
@@ -523,7 +523,8 @@ void UIDelegatesManager::hideMessageBubble()
void UIDelegatesManager::moveMessageBubble(const QRect &anchor)
{
- Q_ASSERT(!m_messageBubbleItem.isNull());
+ if (m_messageBubbleItem.isNull())
+ return;
QQmlProperty(m_messageBubbleItem.data(), QStringLiteral("x")).write(anchor.x());
QQmlProperty(m_messageBubbleItem.data(), QStringLiteral("y")).write(anchor.y() + anchor.size().height());
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index 6b2285c85..99b9c4e6f 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -61,7 +61,7 @@ isQMLTestSupportApiEnabled() {
DEFINES += ENABLE_QML_TESTSUPPORT_API
}
-!contains(WEBENGINE_CONFIG, no_spellcheck) {
+contains(WEBENGINE_CONFIG, use_spellchecker) {
DEFINES += ENABLE_SPELLCHECK
}
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 1004b3e92..ca160c362 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -333,6 +333,11 @@ void QWebEnginePagePrivate::adoptNewWindowImpl(QWebEnginePage *newPage,
if (!initialGeometry.isEmpty())
emit newPage->geometryChangeRequested(initialGeometry);
+ // If the constructor of the QWebEnginePage descendant set a web channel,
+ // set it on the new adapter.
+ newWebContents->setWebChannel(newPage->d_func()->webChannel
+ , newPage->d_func()->webChannelWorldId);
+
// Page has finished the adoption process.
newPage->d_func()->m_isBeingAdopted = false;
}
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index a400b5792..886a7207e 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -98,8 +98,8 @@ using QtWebEngineCore::BrowserContextAdapter;
QWebEngineUrlSchemeHandler::requestStarted() as QWebEngineUrlRequestJob objects.
Spellchecking HTML form fields can be enabled per profile by using the setSpellCheckEnabled()
- method and the current language used for spellchecking can be set by using the
- setSpellCheckLanguage() method.
+ method and the current languages used for spellchecking can be set by using the
+ setSpellCheckLanguages() method.
*/
@@ -565,39 +565,59 @@ QWebEngineProfile *QWebEngineProfile::defaultProfile()
/*!
\since 5.8
- Sets the current \a language for the spell checker.
- The language should match the name of the \c .bdic dictionary.
- For example, the \a language \c en-US will load the \c en-US.bdic
+ Sets the current list of \a languages for the spell checker.
+ Each language should match the name of the \c .bdic dictionary.
+ For example, the language \c en-US will load the \c en-US.bdic
dictionary file.
- The web engine checks for the \c qtwebengine_dictionaries subdirectory
- first in the local directory and if it is not found in the Qt
- installation directory:
+ Qt WebEngine checks for the \c qtwebengine_dictionaries subdirectory
+ first in the local directory and if it is not found, in the Qt
+ installation directory.
+
+ On macOS, depending on how Qt WebEngine is configured at build time, there are two possibilities
+ how spellchecking data is found:
+
+ \list
+ \li Hunspell dictionaries (default) - .bdic dictionaries are used, just like on other
+ platforms
+ \li Native dictionaries - the macOS spellchecking APIs are used (which means the results
+ will depend on the installed OS dictionaries)
+ \endlist
+
+ Thus, in the macOS Hunspell case, Qt WebEngine will look in the \e qtwebengine_dictionaries
+ subdirectory located inside the application bundle \c Resources directory, and also in the
+ \c Resources directory located inside the Qt framework bundle.
+
+ To summarize, in case of Hunspell usage, the following paths are considered:
\list
\li QCoreApplication::applicationDirPath()/qtwebengine_dictionaries
+ or QCoreApplication::applicationDirPath()/../Contents/Resources/qtwebengine_dictionaries
+ (on macOS)
\li [QLibraryInfo::DataPath]/qtwebengine_dictionaries
+ or path/to/QtWebEngineCore.framework/Resources/qtwebengine_dictionaries (Qt framework
+ bundle on macOS)
\endlist
For more information about how to compile \c .bdic dictionaries, see the
\l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}.
*/
-void QWebEngineProfile::setSpellCheckLanguage(const QString &language)
+void QWebEngineProfile::setSpellCheckLanguages(const QStringList &languages)
{
Q_D(QWebEngineProfile);
- d->browserContext()->setSpellCheckLanguage(language);
+ d->browserContext()->setSpellCheckLanguages(languages);
}
/*!
\since 5.8
- Returns the language used by the spell checker.
+ Returns the list of languages used by the spell checker.
*/
-QString QWebEngineProfile::spellCheckLanguage() const
+QStringList QWebEngineProfile::spellCheckLanguages() const
{
const Q_D(QWebEngineProfile);
- return d->browserContext()->spellCheckLanguage();
+ return d->browserContext()->spellCheckLanguages();
}
/*!
diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h
index 704414bcf..1ce4bfe17 100644
--- a/src/webenginewidgets/api/qwebengineprofile.h
+++ b/src/webenginewidgets/api/qwebengineprofile.h
@@ -121,8 +121,8 @@ public:
void clearHttpCache();
- void setSpellCheckLanguage(const QString &language);
- QString spellCheckLanguage() const;
+ void setSpellCheckLanguages(const QStringList &languages);
+ QStringList spellCheckLanguages() const;
void setSpellCheckEnabled(bool enabled);
bool isSpellCheckEnabled() const;
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 6171391e3..8b4053e73 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -107,6 +107,7 @@ static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *obje
QWebEngineViewPrivate::QWebEngineViewPrivate()
: page(0)
, m_pendingContextMenuEvent(false)
+ , m_dragEntered(false)
{
#ifndef QT_NO_ACCESSIBILITY
QAccessible::installFactory(&webAccessibleFactory);
@@ -350,7 +351,10 @@ void QWebEngineView::dragEnterEvent(QDragEnterEvent *e)
{
Q_D(QWebEngineView);
e->accept();
+ if (d->m_dragEntered)
+ d->page->d_ptr->adapter->leaveDrag();
d->page->d_ptr->adapter->enterDrag(e, mapToGlobal(e->pos()));
+ d->m_dragEntered = true;
}
/*!
@@ -359,8 +363,11 @@ void QWebEngineView::dragEnterEvent(QDragEnterEvent *e)
void QWebEngineView::dragLeaveEvent(QDragLeaveEvent *e)
{
Q_D(QWebEngineView);
+ if (!d->m_dragEntered)
+ return;
e->accept();
d->page->d_ptr->adapter->leaveDrag();
+ d->m_dragEntered = false;
}
/*!
@@ -369,6 +376,8 @@ void QWebEngineView::dragLeaveEvent(QDragLeaveEvent *e)
void QWebEngineView::dragMoveEvent(QDragMoveEvent *e)
{
Q_D(QWebEngineView);
+ if (!d->m_dragEntered)
+ return;
QtWebEngineCore::WebContentsAdapter *adapter = d->page->d_ptr->adapter.data();
Qt::DropAction dropAction = adapter->updateDragPosition(e, mapToGlobal(e->pos()));
if (Qt::IgnoreAction == dropAction) {
@@ -385,8 +394,11 @@ void QWebEngineView::dragMoveEvent(QDragMoveEvent *e)
void QWebEngineView::dropEvent(QDropEvent *e)
{
Q_D(QWebEngineView);
+ if (!d->m_dragEntered)
+ return;
e->accept();
d->page->d_ptr->adapter->endDragging(e->pos(), mapToGlobal(e->pos()));
+ d->m_dragEntered = false;
}
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/webenginewidgets/api/qwebengineview_p.h b/src/webenginewidgets/api/qwebengineview_p.h
index b98c553f4..45b3e266e 100644
--- a/src/webenginewidgets/api/qwebengineview_p.h
+++ b/src/webenginewidgets/api/qwebengineview_p.h
@@ -71,6 +71,7 @@ public:
QWebEnginePage *page;
bool m_pendingContextMenuEvent;
+ bool m_dragEntered;
};
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/webenginewidgets/doc/snippets/qtwebengine_build_snippet.qdoc b/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc
index dcdd82e04..dcdd82e04 100644
--- a/src/webenginewidgets/doc/snippets/qtwebengine_build_snippet.qdoc
+++ b/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc
index 59d7bc5d1..abfd17ce3 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc
@@ -28,7 +28,6 @@
/*!
\page qtwebenginewidgets-index.html
\title Qt WebEngine Widgets
- \ingroup modules
\brief Provides a web browser engine as well as C++ classes to render web content and interact
with it.
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc
index d0f2fd930..959f96b10 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc
@@ -40,9 +40,9 @@
To include the definitions of the module's classes, use the
following directive:
- \snippet qtwebengine_build_snippet.qdoc 1
+ \snippet qtwebenginewidgets_build_snippet.qdoc 1
To link against the module, add the following to your qmake project file:
- \snippet qtwebengine_build_snippet.qdoc 0
+ \snippet qtwebenginewidgets_build_snippet.qdoc 0
*/
diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
index 69bac36c8..07afd6501 100644
--- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
@@ -164,12 +164,12 @@
/*!
\fn void QWebEngineSettings::setFontSize(FontSize type, int size)
- Sets the font size for \a type to \a size.
+ Sets the font size for \a type to \a size in pixels.
*/
/*!
\fn int QWebEngineSettings::fontSize(FontSize type) const
- Returns the default font size for \a type.
+ Returns the default font size for \a type in pixels.
*/
/*!
diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
index 43011de0e..eb3a3931a 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -55,6 +55,7 @@
#include <QSGSimpleRectNode>
#include <QSGSimpleTextureNode>
#endif
+#include <private/qwidget_p.h>
namespace QtWebEngineCore {
@@ -392,10 +393,22 @@ bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event)
return true;
}
break;
+ case QEvent::DragEnter:
+ case QEvent::DragLeave:
+ case QEvent::DragMove:
+ case QEvent::Drop:
+ // Let the parent handle these events.
+ return false;
default:
break;
}
+ QEvent::Type type = event->type();
+ if (type == QEvent::FocusIn) {
+ QWidgetPrivate *d = QWidgetPrivate::get(this);
+ d->updateWidgetTransform(event);
+ }
+
if (event->type() == QEvent::MouseButtonDblClick) {
// QWidget keeps the Qt4 behavior where the DblClick event would replace the Press event.
// QtQuick is different by sending both the Press and DblClick events for the second press
diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro
index f1bb86df4..64e475422 100644
--- a/src/webenginewidgets/webenginewidgets.pro
+++ b/src/webenginewidgets/webenginewidgets.pro
@@ -4,7 +4,7 @@ TARGET = QtWebEngineWidgets
DEFINES += QT_BUILD_WEBENGINEWIDGETS_LIB
QT += webenginecore widgets network quick
-QT_PRIVATE += quick-private gui-private core-private quickwidgets
+QT_PRIVATE += quick-private gui-private core-private widgets-private quickwidgets
INCLUDEPATH += $$PWD api ../core ../core/api ../webengine/api
@@ -48,7 +48,7 @@ HEADERS = \
DEFINES += QT_UI_DELEGATES
}
-!contains(WEBENGINE_CONFIG, no_spellcheck) {
+contains(WEBENGINE_CONFIG, use_spellchecker) {
DEFINES += ENABLE_SPELLCHECK
}
diff --git a/sync.profile b/sync.profile
index e713faee4..4cc549106 100644
--- a/sync.profile
+++ b/sync.profile
@@ -10,20 +10,3 @@
);
%classnames = (
);
-
-# Module dependencies.
-# Every module that is required to build this module should have one entry.
-# Each of the module version specifiers can take one of the following values:
-# - A specific Git revision.
-# - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch)
-#
-%dependencies = (
- "qtbase" => "",
- "qtdeclarative" => "",
- "qtlocation" => "",
- "qttools" => "",
-# FIXME: take examples out into their own module to avoid a potential circular dependency later ?
- "qtquickcontrols" => "",
- "qtquickcontrols2" => "",
- "qtwebchannel" => "",
-);
diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST
index 16abe5ff6..d281020df 100644
--- a/tests/auto/quick/qmltests/BLACKLIST
+++ b/tests/auto/quick/qmltests/BLACKLIST
@@ -1,23 +1,11 @@
[DesktopWebEngineViewLinkHovered::test_linkHovered]
*
+[DesktopWebEngineViewLinkHovered::test_linkHoveredDoesntEmitRepeated]
+*
+
[WebViewGeopermission::test_deniedGeolocationByUser]
osx
[WebViewGeopermission::test_geoPermissionRequest]
osx
-
-[WebEngineViewFocusOnNavigation::test_focusOnNavigation]
-*
-
-[WebEngineViewLoadUrl::test_urlProperty]
-windows
-
-[WebEngineViewSettings::test_javascriptDisabled]
-windows
-
-[WebEngineViewUnhandledKeyEventPropagation::test_keyboardModifierMapping]
-windows
-
-[WebEngineViewSource::test_viewSourceURL]
-windows
diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
index 0d2a34645..aa1f77942 100644
--- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml
+++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
@@ -27,7 +27,7 @@
****************************************************************************/
import QtQuick 2.0
-import QtTest 1.0
+import QtTest 1.1
import QtWebEngine 1.3
WebEngineView {
@@ -62,7 +62,27 @@ WebEngineView {
return predicate()
}
+ function getActiveElementId() {
+ var activeElementId;
+ runJavaScript("document.activeElement.id", function(result) {
+ activeElementId = result;
+ });
+ testCase.tryVerify(function() { return activeElementId != undefined });
+ return activeElementId;
+ }
+
+ function verifyElementHasFocus(element) {
+ testCase.tryVerify(function() { return getActiveElementId() == element; }, 5000,
+ "Element \"" + element + "\" has focus");
+ }
+
+ function setFocusToElement(element) {
+ runJavaScript("document.getElementById('" + element + "').focus()");
+ verifyElementHasFocus(element);
+ }
+
TestResult { id: testResult }
+ TestCase { id: testCase }
onLoadingChanged: {
loadStatus = loadRequest.status
diff --git a/tests/auto/quick/qmltests/data/favicon-candidates-gray.html b/tests/auto/quick/qmltests/data/favicon-candidates-gray.html
index 3cbc4a4c3..ebea35b02 100644
--- a/tests/auto/quick/qmltests/data/favicon-candidates-gray.html
+++ b/tests/auto/quick/qmltests/data/favicon-candidates-gray.html
@@ -11,11 +11,11 @@
<h1>Gray Candidate Favicons Test</h1>
<table style="width:100%">
<tr>
- <td align="center"><img src="icons/gray16.png" height="16" width="16" /></td>
- <td align="center"><img src="icons/gray32.png" height="32" width="32" /></td>
- <td align="center"><img src="icons/gray64.png" height="64" width="64" /></td>
- <td align="center"><img src="icons/gray128.png" height="128" width="128" /></td>
- <td align="center"><img src="icons/gray255.png" height="255" width="255" /></td>
+ <td align="center"><img src="icons/gray16.png" height="16" width="16" border="1" /></td>
+ <td align="center"><img src="icons/gray32.png" height="32" width="32" border="1" /></td>
+ <td align="center"><img src="icons/gray64.png" height="64" width="64" border="1" /></td>
+ <td align="center"><img src="icons/gray128.png" height="128" width="128" border="1" /></td>
+ <td align="center"><img src="icons/gray255.png" height="255" width="255" border="1" /></td>
</tr>
<tr>
<td align="center">16x16</td>
diff --git a/tests/auto/quick/qmltests/data/favicon-multi-gray.html b/tests/auto/quick/qmltests/data/favicon-multi-gray.html
index 9b9b7432d..24b71640f 100644
--- a/tests/auto/quick/qmltests/data/favicon-multi-gray.html
+++ b/tests/auto/quick/qmltests/data/favicon-multi-gray.html
@@ -7,11 +7,11 @@
<h1>Gray Multi-sized Favicon Test</h1>
<table style="width:100%">
<tr>
- <td align="center"><img src="icons/gray16.png" height="16" width="16" /></td>
- <td align="center"><img src="icons/gray32.png" height="32" width="32" /></td>
- <td align="center"><img src="icons/gray64.png" height="64" width="64" /></td>
- <td align="center"><img src="icons/gray128.png" height="128" width="128" /></td>
- <td align="center"><img src="icons/gray255.png" height="255" width="255" /></td>
+ <td align="center"><img src="icons/gray16.png" height="16" width="16" border="1" /></td>
+ <td align="center"><img src="icons/gray32.png" height="32" width="32" border="1" /></td>
+ <td align="center"><img src="icons/gray64.png" height="64" width="64" border="1" /></td>
+ <td align="center"><img src="icons/gray128.png" height="128" width="128" border="1" /></td>
+ <td align="center"><img src="icons/gray255.png" height="255" width="255" border="1" /></td>
</tr>
<tr>
<td align="center">16x16</td>
diff --git a/tests/auto/quick/qmltests/data/keyboardEvents.html b/tests/auto/quick/qmltests/data/keyboardEvents.html
new file mode 100644
index 000000000..d536d849f
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/keyboardEvents.html
@@ -0,0 +1,98 @@
+<html>
+<head>
+ <style>
+ div {
+ width: 300px;
+ margin-bottom: 10px;
+ }
+
+ #div_container {
+ display: inline-block;
+ }
+
+ #div_container div {
+ width: 100px;
+ height: 100px;
+ border: 2px solid black;
+ padding: 10px;
+ margin: 0 10px 0 10px;
+ float: left;
+ }
+
+ #div_container div:focus {
+ border: 2px solid red;
+ }
+
+ #form_container span {
+ display: block;
+ padding-bottom: 10px;
+ }
+
+ #form_container label {
+ float: left;
+ text-align: right;
+ width: 50px;
+ margin-right: 20px;
+ }
+ </style>
+</head>
+
+<body onload="document.getElementById('first_div').focus()">
+ <div id="div_container">
+ <div id="first_div" tabindex="0">First</div>
+ <div id="second_div" tabindex="0">Second</div>
+ </div>
+
+ <div id="form_container">
+ <form><fieldset>
+ <legend>Form</legend>
+
+ <span>
+ <label for="text_input">text</label>
+ <input id="text_input" type="text" />
+ </span>
+
+ <span>
+ <input id="radio1" type="radio" name="radio">radio1</input>
+ <input id="radio2" type="radio" name="radio">radio2</input>
+ </span>
+
+ <span>
+ <input id="checkbox1" type="checkbox" name="checkbox1" checked="true">checkbox1</input>
+ <input id="checkbox2" type="checkbox" name="checkbox2" checked="true">checkbox2</input>
+ </span>
+
+ <span>
+ <label for="number_input">number</label>
+ <input id="number_input" type="number" min="0" max="10" value="5" />
+ </span>
+
+ <span>
+ <label for="range_input">range</label>
+ <input id="range_input" type="range" min="0" max="10" value="5" />
+ </span>
+
+ <span>
+ <label for="search_input">search</label>
+ <input id="search_input" type="search" value="test" />
+ </span>
+
+ <input id="submit_button" type="submit" value="Submit" />
+ </fieldset></form>
+ </div>
+
+ <div>
+ <select id="combobox">
+ <option value="a">a</option>
+ <option value="b">b</option>
+ <option value="c">c</option>
+ </select>
+ </div>
+
+ <div>
+ <a id="first_hyperlink" href="">First</a>
+ <br />
+ <a id="second_hyperlink" href="">Second</a>
+ </div>
+</body>
+</html>
diff --git a/tests/auto/quick/qmltests/data/redirect.html b/tests/auto/quick/qmltests/data/redirect.html
index 914e5e35a..44eb6cd28 100644
--- a/tests/auto/quick/qmltests/data/redirect.html
+++ b/tests/auto/quick/qmltests/data/redirect.html
@@ -1,8 +1,9 @@
<!doctype html>
<html>
<head>
-<meta http-equiv="refresh" content="2; url=test1.html"
+ <meta http-equiv="refresh" content="2; url=test1.html">
</head>
<body>
+ Redirecting to test1.html
</body>
</html>
diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml
index 904a8feb2..4761513c1 100644
--- a/tests/auto/quick/qmltests/data/tst_findText.qml
+++ b/tests/auto/quick/qmltests/data/tst_findText.qml
@@ -107,5 +107,24 @@ TestWebEngineView {
tryCompare(webEngineView, "matchCount", 0)
verify(findFailed)
}
+
+ function test_findTextAfterNotFound() {
+ var findFlags = 0
+ webEngineView.url = Qt.resolvedUrl("about:blank")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ webEngineView.clear()
+ webEngineView.findText("hello", findFlags, webEngineView.findTextCallback)
+ tryCompare(webEngineView, "matchCount", 0)
+ verify(findFailed)
+
+ webEngineView.url = Qt.resolvedUrl("test1.html")
+ verify(webEngineView.waitForLoadSucceeded())
+
+ webEngineView.clear()
+ webEngineView.findText("hello", findFlags, webEngineView.findTextCallback)
+ tryCompare(webEngineView, "matchCount", 1)
+ verify(!findFailed)
+ }
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml
index ce0fa2e31..93410a727 100644
--- a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml
+++ b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml
@@ -67,8 +67,6 @@ Item {
TestCase {
name: "WebEngineViewFocusOnNavigation"
when: windowShown
- function init() {
- }
function test_focusOnNavigation_data() {
return [
@@ -79,18 +77,9 @@ Item {
]
}
- function triggerJavascriptFocus() {
- var callbackCalled = false;
- webView.runJavaScript("document.getElementById(\"input\").focus()", function(result) {
- callbackCalled = true;
- });
- wait(100);
- verify(callbackCalled);
- }
-
function loadAndTriggerFocusAndCompare(data) {
verify(webView.waitForLoadSucceeded());
- triggerJavascriptFocus();
+ webView.setFocusToElement("input");
compare(webView.activeFocus, data.viewReceivedFocus);
}
diff --git a/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml b/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml
new file mode 100644
index 000000000..677727632
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_keyboardEvents.qml
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebEngine 1.4
+
+TestWebEngineView {
+ id: webEngineView
+ width: 350
+ height: 480
+
+ TestCase {
+ name: "WebEngineViewKeyboardEvents"
+ when: windowShown
+
+ function isElementChecked(element) {
+ var elementChecked;
+ runJavaScript("document.getElementById('" + element + "').checked", function(result) {
+ elementChecked = result;
+ });
+ tryVerify(function() { return elementChecked != undefined; });
+ return elementChecked;
+ }
+
+ function verifyElementChecked(element, expected) {
+ tryVerify(function() { return expected == isElementChecked(element); }, 5000,
+ "Element \"" + element + "\" is " + (expected ? "" : "not") + " checked");
+ }
+
+ function getElementValue(element) {
+ var elementValue;
+ runJavaScript("document.getElementById('" + element + "').value", function(result) {
+ elementValue = result;
+ });
+ tryVerify(function() { return elementValue != undefined; });
+ return elementValue;
+ }
+
+ function compareElementValue(element, expected) {
+ tryVerify(function() { return expected == getElementValue(element); }, 5000,
+ "Value of element \"" + element + "\" is \"" + expected + "\"");
+ }
+
+ function test_keyboardEvents() {
+ webEngineView.url = Qt.resolvedUrl("keyboardEvents.html");
+ verify(webEngineView.waitForLoadSucceeded());
+
+ var elements = [
+ "first_div", "second_div",
+ "text_input", "radio1", "checkbox1", "checkbox2",
+ "number_input", "range_input", "search_input",
+ "submit_button", "combobox", "first_hyperlink", "second_hyperlink"
+ ];
+
+ // Iterate over the elements of the test page with the Tab key. This tests whether any
+ // element blocks the in-page navigation by Tab.
+ for (var i = 0; i < elements.length; ++i) {
+ verifyElementHasFocus(elements[i])
+ keyPress(Qt.Key_Tab);
+ }
+
+ // Move back to the radio buttons with the Shift+Tab key combination
+ for (var i = 0; i < 10; ++i)
+ keyPress(Qt.Key_Tab, Qt.ShiftModifier);
+ verifyElementHasFocus("radio2");
+
+ // Test the Space key by checking a radio button
+ verifyElementChecked("radio2", false);
+ keyClick(Qt.Key_Space);
+ verifyElementChecked("radio2", true);
+
+ // Test the Left key by switching the radio button
+ verifyElementChecked("radio1", false);
+ keyPress(Qt.Key_Left);
+ verifyElementHasFocus("radio1");
+ verifyElementChecked("radio1", true);
+
+ // Test the Space key by unchecking a checkbox
+ setFocusToElement("checkbox1");
+ verifyElementChecked("checkbox1", true);
+ keyClick(Qt.Key_Space);
+ verifyElementChecked("checkbox1", false);
+
+ // Test the Up and Down keys by changing the value of a spinbox
+ setFocusToElement("number_input");
+ compareElementValue("number_input", 5);
+ keyPress(Qt.Key_Up);
+ compareElementValue("number_input", 6);
+ keyPress(Qt.Key_Down);
+ compareElementValue("number_input", 5);
+
+ // Test the Left, Right, Home, PageUp, End and PageDown keys by changing the value of a slider
+ setFocusToElement("range_input");
+ compareElementValue("range_input", 5);
+ keyPress(Qt.Key_Left);
+ compareElementValue("range_input", 4);
+ keyPress(Qt.Key_Right);
+ compareElementValue("range_input", 5);
+ keyPress(Qt.Key_Home);
+ compareElementValue("range_input", 0);
+ keyPress(Qt.Key_PageUp);
+ compareElementValue("range_input", 1);
+ keyPress(Qt.Key_End);
+ compareElementValue("range_input", 10);
+ keyPress(Qt.Key_PageDown);
+ compareElementValue("range_input", 9);
+
+ // Test the Escape key by removing the content of a search field
+ setFocusToElement("search_input");
+ compareElementValue("search_input", "test");
+ keyPress(Qt.Key_Escape);
+ compareElementValue("search_input", "");
+
+ // Test the alpha keys by changing the values in a combobox
+ setFocusToElement("combobox");
+ compareElementValue("combobox", "a");
+ keyPress(Qt.Key_B);
+ compareElementValue("combobox", "b");
+ // Must wait with the second key press to simulate selection of another element
+ wait(1000);
+ keyPress(Qt.Key_C);
+ compareElementValue("combobox", "c");
+
+ // Test the Enter key by loading a page with a hyperlink
+ setFocusToElement("first_hyperlink");
+ keyPress(Qt.Key_Enter);
+ verify(webEngineView.waitForLoadSucceeded());
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
index ae60e5f5e..e0a8c0a41 100644
--- a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
+++ b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
@@ -52,24 +52,26 @@ TestWebEngineView {
onTriggered: parent.when = true
}
+ function getPressedModifiers() {
+ var pressedModifiers;
+ runJavaScript("getPressedModifiers()", function(result) {
+ pressedModifiers = result;
+ });
+ tryVerify(function() { return pressedModifiers != undefined });
+ return pressedModifiers;
+ }
+
function test_keyboardModifierMapping() {
webEngineView.url = Qt.resolvedUrl("keyboardModifierMapping.html")
waitForLoadSucceeded();
titleSpy.wait()
- var callbackCalled = false;
// Alt
keyPress(Qt.Key_Alt);
titleSpy.wait()
- runJavaScript("getPressedModifiers()", function(result) {
- compare(result, "alt:pressed ctrl:no meta:no");
- callbackCalled = true;
- });
- wait(100);
- verify(callbackCalled);
+ compare(getPressedModifiers(), "alt:pressed ctrl:no meta:no");
keyRelease(Qt.Key_Alt)
titleSpy.wait()
- callbackCalled = false;
// Ctrl
// On mac Qt automatically translates Meta to Ctrl and vice versa.
@@ -78,36 +80,18 @@ TestWebEngineView {
// For testing we assume that the flag Qt::AA_MacDontSwapCtrlAndMeta is NOT set.
keyPress(Qt.platform.os == "osx" ? Qt.Key_Meta : Qt.Key_Control);
titleSpy.wait()
- runJavaScript("getPressedModifiers()", function(result) {
- compare(result, "alt:released ctrl:pressed meta:no");
- callbackCalled = true;
- });
- wait(100);
- verify(callbackCalled);
+ compare(getPressedModifiers(), "alt:released ctrl:pressed meta:no");
keyRelease(Qt.platform.os == "osx" ? Qt.Key_Meta : Qt.Key_Control);
titleSpy.wait()
- callbackCalled = false;
// Meta (Command on Mac)
keyPress(Qt.platform.os == "osx" ? Qt.Key_Control : Qt.Key_Meta);
titleSpy.wait()
- runJavaScript("getPressedModifiers()", function(result) {
- compare(result, "alt:released ctrl:released meta:pressed");
- callbackCalled = true;
- });
- wait(100);
- verify(callbackCalled);
+ compare(getPressedModifiers(), "alt:released ctrl:released meta:pressed");
keyRelease(Qt.platform.os == "osx" ? Qt.Key_Control : Qt.Key_Meta);
titleSpy.wait()
- callbackCalled = false;
- runJavaScript("getPressedModifiers()", function(result) {
- compare(result, "alt:released ctrl:released meta:released");
- callbackCalled = true;
- });
- wait(100);
- verify(callbackCalled);
- callbackCalled = false;
+ compare(getPressedModifiers(), "alt:released ctrl:released meta:released");
}
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
index 3ce03df70..2a43e1577 100644
--- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml
+++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml
@@ -35,152 +35,249 @@ TestWebEngineView {
width: 400
height: 300
- property var lastUrl
- property bool watchProgress: false
- property int numLoadStarted: 0
- property int numLoadSucceeded: 0
+ property var loadRequestArray: []
- focus: true
-
- onLoadProgressChanged: {
- if (watchProgress && webEngineView.loadProgress != 100) {
- watchProgress = false
- url = ''
- }
+ onLoadingChanged: {
+ loadRequestArray.push({
+ "status": loadRequest.status,
+ "url": loadRequest.url,
+ "activeUrl": webEngineView.url
+ });
}
- onLoadingChanged: {
- if (loadRequest.status == WebEngineView.LoadStartedStatus)
- ++numLoadStarted
- if (loadRequest.status == WebEngineView.LoadSucceededStatus)
- ++numLoadSucceeded
+ function clear() {
+ // Reset loadStatus for waitForLoadSucceded
+ webEngineView.loadStatus = null;
+ loadRequestArray = [];
}
TestCase {
name: "WebEngineViewLoadUrl"
when: windowShown
+ function init() {
+ webEngineView.clear();
+ }
+
function test_loadIgnoreEmptyUrl() {
- var url = Qt.resolvedUrl("test1.html")
-
- webEngineView.url = url
- verify(webEngineView.waitForLoadSucceeded())
- compare(numLoadStarted, 1)
- compare(numLoadSucceeded, 1)
- compare(webEngineView.url, url)
-
- lastUrl = webEngineView.url
- webEngineView.url = ''
- wait(1000)
- compare(numLoadStarted, 1)
- compare(numLoadSucceeded, 1)
- compare(webEngineView.url, lastUrl)
-
- webEngineView.url = 'about:blank'
- verify(webEngineView.waitForLoadSucceeded())
- compare(numLoadStarted, 2)
- compare(numLoadSucceeded, 2)
- compare(webEngineView.url, 'about:blank')
+ var url = Qt.resolvedUrl("test1.html");
+ webEngineView.url = url;
+ verify(webEngineView.waitForLoadSucceeded());
+ compare(loadRequestArray[0].status, WebEngineView.LoadStartedStatus);
+ compare(loadRequestArray[1].status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequestArray.length, 2);
+ compare(webEngineView.url, url);
+ webEngineView.clear();
+
+ var lastUrl = webEngineView.url;
+ webEngineView.url = "";
+ wait(1000);
+ compare(loadRequestArray.length, 0);
+ compare(webEngineView.url, lastUrl);
+ webEngineView.clear();
+
+ var aboutBlank = "about:blank";
+ webEngineView.url = aboutBlank;
+ verify(webEngineView.waitForLoadSucceeded());
+ compare(loadRequestArray[0].status, WebEngineView.LoadStartedStatus);
+ compare(loadRequestArray[1].status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequestArray.length, 2);
+ compare(webEngineView.url, aboutBlank);
+ webEngineView.clear();
// It shouldn't interrupt any ongoing load when an empty url is used.
- watchProgress = true
- webEngineView.url = url
- webEngineView.waitForLoadSucceeded()
- compare(numLoadStarted, 3)
- compare(numLoadSucceeded, 3)
- verify(!watchProgress)
- compare(webEngineView.url, url)
+ var watchProgress = true;
+ var handleLoadProgress = function() {
+ if (webEngineView.loadProgress != 100) {
+ webEngineView.url = "";
+ watchProgress = false;
+ }
+ }
+ webEngineView.loadProgressChanged.connect(handleLoadProgress);
+ webEngineView.url = url;
+ verify(webEngineView.waitForLoadSucceeded());
+ compare(loadRequestArray[0].status, WebEngineView.LoadStartedStatus);
+ compare(loadRequestArray[1].status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequestArray.length, 2);
+ verify(!watchProgress);
+ compare(webEngineView.url, url);
+ webEngineView.loadProgressChanged.disconnect(handleLoadProgress);
+ webEngineView.clear();
}
function test_urlProperty() {
- WebEngine.settings.errorPageEnabled = false
+ WebEngine.settings.errorPageEnabled = false;
- var url = Qt.resolvedUrl("test1.html")
+ var loadRequest = null;
- webEngineView.url = url
- compare(webEngineView.url, url)
- verify(webEngineView.waitForLoadSucceeded())
- compare(webEngineView.url, url)
+ // Test succeeded load
+ var url = Qt.resolvedUrl("test1.html");
+ webEngineView.url = url;
+ tryCompare(loadRequestArray, "length", 2);
- var bogusSite = "http://www.somesitethatdoesnotexist.abc/"
- webEngineView.url = bogusSite
- compare(webEngineView.url, bogusSite)
- verify(webEngineView.waitForLoadFailed())
- compare(webEngineView.url, url)
+ loadRequest = loadRequestArray[0];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.activeUrl, url);
+ loadRequest = loadRequestArray[1];
+ compare(loadRequest.status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequest.activeUrl, url);
+ webEngineView.clear();
+
+ // Test failed load
+ var bogusSite = "http://www.somesitethatdoesnotexist.abc/";
+ webEngineView.url = bogusSite;
+ tryCompare(loadRequestArray, "length", 2);
+
+ loadRequest = loadRequestArray[0];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.activeUrl, bogusSite);
+ loadRequest = loadRequestArray[1];
+ compare(loadRequest.status, WebEngineView.LoadFailedStatus);
+ compare(loadRequest.activeUrl, url);
+ webEngineView.clear();
+
+ // Test page redirection
+ var redirectUrl = Qt.resolvedUrl("redirect.html");
+ webEngineView.url = redirectUrl;
+ tryCompare(loadRequestArray, "length", 4);
- webEngineView.url = "about:blank" // Reset from previous test
- verify(webEngineView.waitForLoadSucceeded())
+ loadRequest = loadRequestArray[0];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.activeUrl, redirectUrl);
+ loadRequest = loadRequestArray[1];
+ compare(loadRequest.status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequest.activeUrl, redirectUrl);
+ loadRequest = loadRequestArray[2];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.activeUrl, redirectUrl);
+ loadRequest = loadRequestArray[3];
+ compare(loadRequest.status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequest.activeUrl, url);
+ webEngineView.clear();
+ // Test clicking on a hyperlink
+ var linkUrl = Qt.resolvedUrl("link.html");
+ webEngineView.url = linkUrl;
+ tryCompare(loadRequestArray, "length", 2);
+
+ loadRequest = loadRequestArray[0];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.activeUrl, linkUrl);
+ loadRequest = loadRequestArray[1];
+ compare(loadRequest.status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequest.activeUrl, linkUrl);
+ webEngineView.clear();
+
+ var lastUrl = webEngineView.url;
+ mouseClick(webEngineView, 10, 10, Qt.LeftButton, Qt.NoModifiers, 50);
+ tryCompare(loadRequestArray, "length", 2);
+
+ loadRequest = loadRequestArray[0];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.url, url);
+ compare(loadRequest.activeUrl, lastUrl);
+ loadRequest = loadRequestArray[1];
+ compare(loadRequest.status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequest.url, url);
+ compare(loadRequest.activeUrl, url);
+ webEngineView.clear();
+ }
+
+ function test_loadDataUrl() {
+ WebEngine.settings.errorPageEnabled = false;
+
+ var loadRequest = null;
+
+ // Test load of a data URL
+ var dataUrl = "data:text/html,foo";
+ webEngineView.url = dataUrl;
+ tryCompare(loadRequestArray, "length", 2);
+
+ loadRequest = loadRequestArray[0];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.activeUrl, dataUrl);
+ loadRequest = loadRequestArray[1];
+ compare(loadRequest.status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequest.activeUrl, dataUrl);
+ webEngineView.clear();
+
+ // Test loadHtml after a failed load
+ var aboutBlank = "about:blank";
+ webEngineView.url = aboutBlank; // Reset from previous test
+ verify(webEngineView.waitForLoadSucceeded());
+ webEngineView.clear();
+
+ var bogusSite = "http://www.somesitethatdoesnotexist.abc/";
var handleLoadFailed = function(loadRequest) {
if (loadRequest.status == WebEngineView.LoadFailedStatus) {
- webEngineView.loadHtml("load failed", bogusSite)
- // Since the load did not succeed the active url is the
- // url of the previous successful load.
- compare(webEngineView.url, "about:blank")
- compare(loadRequest.url, bogusSite)
+ // loadHtml constructs data URL
+ webEngineView.loadHtml("load failed", bogusSite);
+ compare(loadRequest.url, bogusSite);
}
}
- webEngineView.loadingChanged.connect(handleLoadFailed)
+ webEngineView.loadingChanged.connect(handleLoadFailed);
webEngineView.url = bogusSite
- compare(webEngineView.url, bogusSite)
- verify(webEngineView.waitForLoadSucceeded())
- compare(webEngineView.url, bogusSite)
- webEngineView.loadingChanged.disconnect(handleLoadFailed)
-
- var dataUrl = "data:text/html,foo"
- webEngineView.url = dataUrl
- compare(webEngineView.url, dataUrl)
- verify(webEngineView.waitForLoadSucceeded()) // data:text/html,foo is loaded
- compare(webEngineView.url, dataUrl)
-
- var redirectUrl = Qt.resolvedUrl("redirect.html")
- webEngineView.url = redirectUrl
- compare(webEngineView.url, redirectUrl)
- verify(webEngineView.waitForLoadSucceeded()) // redirect.html is loaded
- compare(webEngineView.url, redirectUrl)
- verify(webEngineView.waitForLoadSucceeded()) // test1.html is loaded
- compare(webEngineView.url, url)
-
- var linkUrl = Qt.resolvedUrl("link.html")
- webEngineView.url = linkUrl
- compare(webEngineView.url, linkUrl)
- verify(webEngineView.waitForLoadSucceeded())
- compare(webEngineView.url, linkUrl)
-
- var handleLoadRequest = function(loadRequest) {
- if (loadRequest.status == WebEngineView.LoadStartedStatus) {
- compare(webEngineView.url, lastUrl)
- compare(loadRequest.url, url)
- }
- if (loadRequest.status == WebEngineView.LoadSuceededStatus) {
- compare(webEngineView.url, loadRequest.url)
- compare(webEngineView.url, url)
- }
- }
- lastUrl = webEngineView.url
- webEngineView.loadingChanged.connect(handleLoadRequest)
- mouseClick(webEngineView, 10, 10, Qt.LeftButton, Qt.NoModifiers, 50)
- verify(webEngineView.waitForLoadSucceeded())
- compare(webEngineView.url, url)
- webEngineView.loadingChanged.disconnect(handleLoadRequest)
+ tryCompare(loadRequestArray, "length", 4);
+ webEngineView.loadingChanged.disconnect(handleLoadFailed);
+
+ loadRequest = loadRequestArray[0];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.activeUrl, bogusSite);
+ loadRequest = loadRequestArray[1];
+ compare(loadRequest.status, WebEngineView.LoadFailedStatus);
+ // Since the load did not succeed the active url is the
+ // URL of the previous successful load.
+ compare(loadRequest.activeUrl, aboutBlank);
+ loadRequest = loadRequestArray[2];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.activeUrl, aboutBlank);
+ loadRequest = loadRequestArray[3];
+ compare(loadRequest.status, WebEngineView.LoadSucceededStatus);
+ compare(loadRequest.activeUrl, bogusSite);
+ webEngineView.clear();
+ }
+
+ function test_QTBUG_56661() {
+ var url = Qt.resolvedUrl("test1.html");
+
+ // Warm up phase
+ webEngineView.url = url;
+ verify(webEngineView.waitForLoadSucceeded());
+
+ // Load data URL
+ var dataUrl = "data:text/html,foo";
+ webEngineView.url = dataUrl;
+ verify(webEngineView.waitForLoadSucceeded());
+
+ // WebEngine should not try to execute user scripts in the
+ // render frame of the warm up phase otherwise the renderer
+ // crashes.
+ webEngineView.url = url;
+ verify(webEngineView.waitForLoadSucceeded());
}
function test_stopStatus() {
- var url = Qt.resolvedUrl("test1.html")
+ var loadRequest = null;
- var handleLoadRequest = function(loadRequest) {
- if (loadRequest.status == WebEngineView.LoadStoppedStatus) {
- compare(webEngineView.url, url)
- compare(loadRequest.url, url)
- }
+ var handleLoadStarted = function(loadRequest) {
+ if (loadRequest.status == WebEngineView.LoadStartedStatus)
+ webEngineView.stop();
}
- webEngineView.loadingChanged.connect(handleLoadRequest)
- webEngineView.url = url
- compare(webEngineView.url, url)
- webEngineView.stop()
- verify(webEngineView.waitForLoadStopped())
- compare(webEngineView.url, url)
- webEngineView.loadingChanged.disconnect(handleLoadRequest)
+ webEngineView.loadingChanged.connect(handleLoadStarted);
+ var url = Qt.resolvedUrl("test1.html");
+ webEngineView.url = url;
+ tryCompare(loadRequestArray, "length", 2);
+ webEngineView.loadingChanged.disconnect(handleLoadStarted);
+
+ loadRequest = loadRequestArray[0];
+ compare(loadRequest.status, WebEngineView.LoadStartedStatus);
+ compare(loadRequest.url, url);
+ compare(loadRequest.activeUrl, url);
+ loadRequest = loadRequestArray[1];
+ compare(loadRequest.status, WebEngineView.LoadStoppedStatus);
+ compare(loadRequest.url, url);
+ compare(loadRequest.activeUrl, url);
+ webEngineView.clear();
}
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
index 5013f2fbe..b1c94e601 100644
--- a/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
+++ b/tests/auto/quick/qmltests/data/tst_navigationRequested.qml
@@ -83,9 +83,6 @@ TestWebEngineView {
when: windowShown
function init() {
- // Workaround for QTBUG-56223
- mouseClick(webEngineView, 0, 0)
-
attributes.clear()
navigationSpy.clear()
shouldIgnoreLinkClicks = false
diff --git a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml
new file mode 100644
index 000000000..754a9e018
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebEngine 1.2
+
+TestWebEngineView {
+ id: webEngineView
+ width: 200
+ height: 400
+
+ property var newViewRequest: null
+ property var dialog: null
+
+ SignalSpy {
+ id: newViewRequestedSpy
+ target: webEngineView
+ signalName: "newViewRequested"
+ }
+
+ onNewViewRequested: {
+ newViewRequest = {
+ "destination": request.destination,
+ "userInitiated": request.userInitiated
+ };
+
+ dialog = Qt.createQmlObject(
+ "import QtQuick.Window 2.0\n" +
+ "Window {\n" +
+ " width: 100; height: 100\n" +
+ " visible: true; flags: Qt.Dialog\n" +
+ " property alias webEngineView: webView\n" +
+ " TestWebEngineView { id: webView; anchors.fill: parent }\n" +
+ "}", webEngineView);
+
+ request.openIn(dialog.webEngineView);
+ }
+
+ TestCase {
+ id: test
+ name: "NewViewRequest"
+ when: windowShown
+
+ function init() {
+ webEngineView.url = Qt.resolvedUrl("about:blank");
+ verify(webEngineView.waitForLoadSucceeded());
+
+ newViewRequestedSpy.clear();
+ newViewRequest = null;
+ }
+
+ function cleanup() {
+ if (dialog)
+ dialog.destroy();
+ }
+
+ function test_jsWindowOpen() {
+ // Open an empty page in a new tab
+ webEngineView.loadHtml(
+ "<html><head><script>" +
+ " function popup() { window.open(''); }" +
+ "</script></head>" +
+ "<body onload='popup()'></body></html>");
+ verify(webEngineView.waitForLoadSucceeded());
+ tryCompare(newViewRequestedSpy, "count", 1);
+
+ compare(newViewRequest.destination, WebEngineView.NewViewInTab);
+ verify(!newViewRequest.userInitiated);
+
+ verify(dialog.webEngineView.waitForLoadSucceeded);
+ compare(dialog.webEngineView.url, "");
+ newViewRequestedSpy.clear();
+ dialog.destroy();
+
+ // Open an empty page in a new dialog
+ webEngineView.loadHtml(
+ "<html><head><script>" +
+ " function popup() { window.open('', '_blank', 'width=200,height=100'); }" +
+ "</script></head>" +
+ "<body onload='popup()'></body></html>");
+ verify(webEngineView.waitForLoadSucceeded());
+ tryCompare(newViewRequestedSpy, "count", 1);
+
+ compare(newViewRequest.destination, WebEngineView.NewViewInDialog);
+ verify(!newViewRequest.userInitiated);
+ verify(dialog.webEngineView.waitForLoadSucceeded);
+ newViewRequestedSpy.clear();
+ dialog.destroy();
+
+ // Open an empty page in a new dialog by user
+ webEngineView.loadHtml(
+ "<html><head><script>" +
+ " function popup() { window.open('', '_blank', 'width=200,height=100'); }" +
+ "</script></head>" +
+ "<body onload=\"document.getElementById('popupButton').focus();\">" +
+ " <button id='popupButton' onclick='popup()'>Pop Up!</button>" +
+ "</body></html>");
+ verify(webEngineView.waitForLoadSucceeded());
+ verifyElementHasFocus("popupButton");
+ keyPress(Qt.Key_Enter);
+ tryCompare(newViewRequestedSpy, "count", 1);
+
+ compare(newViewRequest.destination, WebEngineView.NewViewInDialog);
+ verify(newViewRequest.userInitiated);
+ verify(dialog.webEngineView.waitForLoadSucceeded);
+ newViewRequestedSpy.clear();
+ dialog.destroy();
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qmltests/data/tst_settings.qml b/tests/auto/quick/qmltests/data/tst_settings.qml
index aa3a6dc60..0c37d9569 100644
--- a/tests/auto/quick/qmltests/data/tst_settings.qml
+++ b/tests/auto/quick/qmltests/data/tst_settings.qml
@@ -56,7 +56,7 @@ TestWebEngineView {
webEngineView.url = Qt.resolvedUrl("javascript.html");
verify(webEngineView.waitForLoadSucceeded());
- compare(webEngineView.title, "New Title");
+ tryCompare(webEngineView, "title", "New Title");
}
function test_javascriptDisabled() {
@@ -64,7 +64,7 @@ TestWebEngineView {
webEngineView.url = Qt.resolvedUrl("javascript.html");
verify(webEngineView.waitForLoadSucceeded());
- compare(webEngineView.title, "Original Title");
+ tryCompare(webEngineView, "title", "Original Title");
}
function test_localStorageDisabled() {
@@ -73,7 +73,7 @@ TestWebEngineView {
webEngineView.url = Qt.resolvedUrl("localStorage.html");
verify(webEngineView.waitForLoadSucceeded());
- compare(webEngineView.title, "Original Title");
+ tryCompare(webEngineView, "title", "Original Title");
}
function test_localStorageEnabled() {
@@ -84,7 +84,7 @@ TestWebEngineView {
verify(webEngineView.waitForLoadSucceeded());
webEngineView.reload();
verify(webEngineView.waitForLoadSucceeded());
- compare(webEngineView.title, "New Title");
+ tryCompare(webEngineView, "title", "New Title");
}
function test_settingsAffectCurrentViewOnly() {
@@ -100,8 +100,8 @@ TestWebEngineView {
webEngineView2.url = testUrl;
verify(webEngineView2.waitForLoadSucceeded());
- compare(webEngineView.title, "New Title");
- compare(webEngineView2.title, "New Title");
+ tryCompare(webEngineView, "title", "New Title");
+ tryCompare(webEngineView2, "title", "New Title");
webEngineView.settings.javascriptEnabled = false;
@@ -110,8 +110,8 @@ TestWebEngineView {
webEngineView2.url = testUrl;
verify(webEngineView2.waitForLoadSucceeded());
- compare(webEngineView.title, "Original Title");
- compare(webEngineView2.title, "New Title");
+ tryCompare(webEngineView, "title", "Original Title");
+ tryCompare(webEngineView2, "title", "New Title");
webEngineView2.destroy();
}
diff --git a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml
index 87ef16aa2..906dc1658 100644
--- a/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml
+++ b/tests/auto/quick/qmltests/data/tst_unhandledKeyEventPropagation.qml
@@ -68,12 +68,10 @@ Item {
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)
+ tryCompare(parentItem.pressEvents, "length", 1)
compare(parentItem.pressEvents[0], Qt.Key_Left)
- compare(parentItem.releaseEvents.length, 3)
+
+ tryCompare(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_viewSource.qml b/tests/auto/quick/qmltests/data/tst_viewSource.qml
index 79b097b80..8076d99f8 100644
--- a/tests/auto/quick/qmltests/data/tst_viewSource.qml
+++ b/tests/auto/quick/qmltests/data/tst_viewSource.qml
@@ -74,7 +74,7 @@ TestWebEngineView {
function test_viewSource() {
webEngineView.url = Qt.resolvedUrl("test1.html");
verify(webEngineView.waitForLoadSucceeded());
- compare(webEngineView.title, "Test page 1");
+ tryCompare(webEngineView, "title", "Test page 1");
// FIXME(pvarga): Reintroduce this check in the fix for QTBUG-56117
//verify(webEngineView.canViewSource, true);
@@ -83,14 +83,14 @@ TestWebEngineView {
tryCompare(newViewRequestedSpy, "count", 1);
verify(webEngineView.waitForLoadSucceeded());
// The first titleChanged signal is emitted by adoptWebContents()
- tryCompare(titleChangedSpy, "count", 2);
+ tryVerify(function() { return titleChangedSpy.count >= 2; });
compare(viewRequest.destination, WebEngineView.NewViewInTab);
verify(viewRequest.userInitiated);
// FIXME(pvarga): Reintroduce this check in the fix for QTBUG-56117
//verify(!webEngineView.canViewSource);
- compare(webEngineView.title, "test1.html");
+ tryCompare(webEngineView, "title", "test1.html");
compare(webEngineView.url, "view-source:" + Qt.resolvedUrl("test1.html"));
}
@@ -114,14 +114,14 @@ TestWebEngineView {
if (row.loadSucceed) {
verify(webEngineView.waitForLoadSucceeded());
- tryCompare(titleChangedSpy, "count", 1);
+ tryVerify(function() { return titleChangedSpy.count >= 1; });
} else {
verify(webEngineView.waitForLoadFailed());
- tryCompare(titleChangedSpy, "count", 2);
+ tryVerify(function() { return titleChangedSpy.count >= 2; });
}
compare(webEngineView.url, row.url);
- compare(webEngineView.title, row.title);
+ tryCompare(webEngineView, "title", row.title);
// FIXME(pvarga): Reintroduce this check in the fix for QTBUG-56117
//verify(!webEngineView.canViewSource);
}
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index 30c3aab30..4d4268324 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -39,12 +39,14 @@ OTHER_FILES += \
$$PWD/data/test3.html \
$$PWD/data/test4.html \
$$PWD/data/keyboardModifierMapping.html \
+ $$PWD/data/keyboardEvents.html \
$$PWD/data/titleupdate.js \
$$PWD/data/tst_desktopBehaviorLoadHtml.qml \
$$PWD/data/tst_download.qml \
$$PWD/data/tst_favicon.qml \
$$PWD/data/tst_faviconDownload.qml \
$$PWD/data/tst_filePicker.qml \
+ $$PWD/data/tst_findText.qml \
$$PWD/data/tst_focusOnNavigation.qml \
$$PWD/data/tst_formValidation.qml \
$$PWD/data/tst_geopermission.qml \
@@ -58,6 +60,7 @@ OTHER_FILES += \
$$PWD/data/tst_loadUrl.qml \
$$PWD/data/tst_navigationHistory.qml \
$$PWD/data/tst_navigationRequested.qml \
+ $$PWD/data/tst_newViewRequest.qml \
$$PWD/data/tst_properties.qml \
$$PWD/data/tst_runJavaScript.qml \
$$PWD/data/tst_scrollPosition.qml \
@@ -68,6 +71,7 @@ OTHER_FILES += \
$$PWD/data/tst_webchannel.qml \
$$PWD/data/tst_settings.qml \
$$PWD/data/tst_keyboardModifierMapping.qml \
+ $$PWD/data/tst_keyboardEvents.qml \
$$PWD/data/icons/favicon.png \
$$PWD/data/icons/gray128.png \
$$PWD/data/icons/gray16.png \
diff --git a/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp b/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp
index 63ca25396..3ed4bcc71 100644
--- a/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp
+++ b/tests/auto/widgets/qwebengineaccessibility/tst_qwebengineaccessibility.cpp
@@ -25,7 +25,7 @@
#include <qwebenginepage.h>
#include <qwidget.h>
-class tst_QWebEngineView : public QObject
+class tst_QWebEngineAccessibility : public QObject
{
Q_OBJECT
@@ -44,27 +44,27 @@ private Q_SLOTS:
// This will be called before the first test function is executed.
// It is only called once.
-void tst_QWebEngineView::initTestCase()
+void tst_QWebEngineAccessibility::initTestCase()
{
}
// This will be called after the last test function is executed.
// It is only called once.
-void tst_QWebEngineView::cleanupTestCase()
+void tst_QWebEngineAccessibility::cleanupTestCase()
{
}
// This will be called before each test function is executed.
-void tst_QWebEngineView::init()
+void tst_QWebEngineAccessibility::init()
{
}
// This will be called after every test function.
-void tst_QWebEngineView::cleanup()
+void tst_QWebEngineAccessibility::cleanup()
{
}
-void tst_QWebEngineView::noPage()
+void tst_QWebEngineAccessibility::noPage()
{
QWebEngineView webView;
webView.show();
@@ -80,7 +80,7 @@ void tst_QWebEngineView::noPage()
QCOMPARE(document->childCount(), 0);
}
-void tst_QWebEngineView::hierarchy()
+void tst_QWebEngineAccessibility::hierarchy()
{
QWebEngineView webView;
webView.setHtml("<html><body>" \
@@ -139,7 +139,7 @@ void tst_QWebEngineView::hierarchy()
QCOMPARE(input, child);
}
-void tst_QWebEngineView::text()
+void tst_QWebEngineAccessibility::text()
{
QWebEngineView webView;
webView.setHtml("<html><body>" \
@@ -207,7 +207,7 @@ void tst_QWebEngineView::text()
QCOMPARE(input3->text(QAccessible::Value), QStringLiteral("Good day!"));
}
-void tst_QWebEngineView::value()
+void tst_QWebEngineAccessibility::value()
{
QWebEngineView webView;
webView.setHtml("<html><body>" \
@@ -248,5 +248,5 @@ void tst_QWebEngineView::value()
static QByteArrayList params = QByteArrayList()
<< "--force-renderer-accessibility";
-W_QTEST_MAIN(tst_QWebEngineView, params)
+W_QTEST_MAIN(tst_QWebEngineAccessibility, params)
#include "tst_qwebengineaccessibility.moc"
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 166c5a499..f16c42976 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -296,6 +296,7 @@ void tst_QWebEnginePage::cleanupFiles()
void tst_QWebEnginePage::initTestCase()
{
+ QLocale::setDefault(QLocale("en"));
cleanupFiles(); // In case there are old files from previous runs
// Set custom path since the CI doesn't install test plugins.
@@ -4992,6 +4993,8 @@ void tst_QWebEnginePage::viewSource()
QCOMPARE(page.createdWindows.size(), 1);
QTRY_COMPARE(page.createdWindows[0]->url().toString(), QStringLiteral("view-source:%1").arg(url.toString()));
+ // The requested URL should not be about:blank if the qrc scheme is supported
+ QTRY_COMPARE(page.createdWindows[0]->requestedUrl(), url);
QTRY_COMPARE(page.createdWindows[0]->title(), QStringLiteral("view-source:%1").arg(url.toString()));
QVERIFY(!page.createdWindows[0]->action(QWebEnginePage::ViewSource)->isEnabled());
}
@@ -5001,21 +5004,24 @@ void tst_QWebEnginePage::viewSourceURL_data()
QTest::addColumn<QUrl>("userInputUrl");
QTest::addColumn<bool>("loadSucceed");
QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QUrl>("requestedUrl");
QTest::addColumn<QString>("title");
- QTest::newRow("view-source:") << QUrl("view-source:") << true << QUrl("view-source:") << QString("view-source:");
- QTest::newRow("view-source:about:blank") << QUrl("view-source:about:blank") << true << QUrl("view-source:about:blank") << QString("view-source:about:blank");
+ QTest::newRow("view-source:") << QUrl("view-source:") << true << QUrl("view-source:") << QUrl("about:blank") << QString("view-source:");
+ QTest::newRow("view-source:about:blank") << QUrl("view-source:about:blank") << true << QUrl("view-source:about:blank") << QUrl("about:blank") << QString("view-source:about:blank");
- QUrl testLocalUrl = QUrl(QString("view-source:%1").arg(QUrl::fromLocalFile(TESTS_SOURCE_DIR + QLatin1String("qwebenginepage/resources/test1.html")).toString()));
- QUrl testLocalUrlWithoutScheme = QUrl(QString("view-source:%1").arg(TESTS_SOURCE_DIR + QLatin1String("qwebenginepage/resources/test1.html")));
- QTest::newRow(testLocalUrl.toString().toStdString().c_str()) << testLocalUrl << true << testLocalUrl << QString("test1.html");
- QTest::newRow(testLocalUrlWithoutScheme.toString().toStdString().c_str()) << testLocalUrlWithoutScheme << true << testLocalUrl << QString("test1.html");
+ QString localFilePath = QString("%1qwebenginepage/resources/test1.html").arg(TESTS_SOURCE_DIR);
+ QUrl testLocalUrl = QUrl(QString("view-source:%1").arg(QUrl::fromLocalFile(localFilePath).toString()));
+ QUrl testLocalUrlWithoutScheme = QUrl(QString("view-source:%1").arg(localFilePath));
+ QTest::newRow(testLocalUrl.toString().toStdString().c_str()) << testLocalUrl << true << testLocalUrl << QUrl::fromLocalFile(localFilePath) << QString("test1.html");
+ QTest::newRow(testLocalUrlWithoutScheme.toString().toStdString().c_str()) << testLocalUrlWithoutScheme << true << testLocalUrl << QUrl::fromLocalFile(localFilePath) << QString("test1.html");
- QUrl testResourceUrl = QUrl("view-source:qrc:/resources/test1.html");
- QTest::newRow(testResourceUrl.toString().toStdString().c_str()) << testResourceUrl << true << testResourceUrl << testResourceUrl.toString();
+ QString resourcePath = QLatin1String("qrc:/resources/test1.html");
+ QUrl testResourceUrl = QUrl(QString("view-source:%1").arg(resourcePath));
+ QTest::newRow(testResourceUrl.toString().toStdString().c_str()) << testResourceUrl << true << testResourceUrl << QUrl(resourcePath) << testResourceUrl.toString();
- QTest::newRow("view-source:http://non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QString("http://non.existent/ is not available");
- QTest::newRow("view-source:non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QString("http://non.existent/ is not available");
+ QTest::newRow("view-source:http://non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QUrl("http://non.existent/") << QString("http://non.existent/ is not available");
+ QTest::newRow("view-source:non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QUrl("http://non.existent/") << QString("http://non.existent/ is not available");
}
void tst_QWebEnginePage::viewSourceURL()
@@ -5026,6 +5032,7 @@ void tst_QWebEnginePage::viewSourceURL()
QFETCH(QUrl, userInputUrl);
QFETCH(bool, loadSucceed);
QFETCH(QUrl, url);
+ QFETCH(QUrl, requestedUrl);
QFETCH(QString, title);
QWebEnginePage *page = new QWebEnginePage;
@@ -5037,6 +5044,7 @@ void tst_QWebEnginePage::viewSourceURL()
QCOMPARE(arguments.at(0).toBool(), loadSucceed);
QCOMPARE(page->url(), url);
+ QCOMPARE(page->requestedUrl(), requestedUrl);
QCOMPARE(page->title(), title);
QVERIFY(!page->action(QWebEnginePage::ViewSource)->isEnabled());
diff --git a/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.aff b/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.aff
new file mode 100644
index 000000000..ff8185771
--- /dev/null
+++ b/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.aff
@@ -0,0 +1,5 @@
+SET UTF-8
+TRY esianrtolcdugmphbyfvkwzqESIANRTOLCDUGMPHBYFVKWZQ
+
+PFX Q Y 1
+PFX Q 0 q .
diff --git a/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.dic b/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.dic
new file mode 100644
index 000000000..d10ae2600
--- /dev/null
+++ b/tests/auto/widgets/qwebenginespellcheck/dict/de-DE.dic
@@ -0,0 +1,14 @@
+15
+du/Q
+er/Q
+es/Q
+ich/Q
+ihr/Q
+liebe/Q
+lieben/Q
+liebst/Q
+liebt/Q
+qt/Q
+sie/Q
+Sie/Q
+wir/Q
diff --git a/tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro b/tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro
index 437aad937..a36c82e20 100644
--- a/tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro
+++ b/tests/auto/widgets/qwebenginespellcheck/qwebenginespellcheck.pro
@@ -2,7 +2,9 @@ include(../tests.pri)
DISTFILES += \
dict/en-US.dic \
- dict/en-US.aff
+ dict/en-US.aff \
+ dict/de-DE.dic \
+ dict/de-DE.aff \
qtPrepareTool(CONVERT_TOOL, qwebengine_convert_dict)
@@ -13,7 +15,7 @@ debug_and_release {
DICTIONARIES_DIR = qtwebengine_dictionaries
}
-dict.files = $$PWD/dict/en-US.dic
+dict.files = $$PWD/dict/en-US.dic $$PWD/dict/de-DE.dic
dictoolbuild.input = dict.files
dictoolbuild.output = $${DICTIONARIES_DIR}/${QMAKE_FILE_BASE}.bdic
dictoolbuild.commands = $${CONVERT_TOOL} ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
diff --git a/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp
index 534d40f45..4db5b9477 100644
--- a/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp
+++ b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp
@@ -73,8 +73,10 @@ private Q_SLOTS:
void cleanup();
void initTestCase();
void spellCheckLanguage();
+ void spellCheckLanguages();
void spellCheckEnabled();
void spellcheck();
+ void spellcheck_data();
private:
void load();
@@ -86,14 +88,14 @@ void tst_QWebEngineSpellcheck::initTestCase()
QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
QVERIFY(profile);
QVERIFY(!profile->isSpellCheckEnabled());
- QVERIFY(profile->spellCheckLanguage().isEmpty());
+ QVERIFY(profile->spellCheckLanguages().isEmpty());
}
void tst_QWebEngineSpellcheck::init()
{
QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
profile->setSpellCheckEnabled(false);
- profile->setSpellCheckLanguage(QString::null);
+ profile->setSpellCheckLanguages(QStringList());
m_view = new WebView();
}
@@ -113,10 +115,19 @@ void tst_QWebEngineSpellcheck::spellCheckLanguage()
{
QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
QVERIFY(profile);
- profile->setSpellCheckLanguage("en-US");
- QVERIFY(profile->spellCheckLanguage() == "en-US");
+ profile->setSpellCheckLanguages({"en-US"});
+ QVERIFY(profile->spellCheckLanguages() == QStringList({"en-US"}));
}
+void tst_QWebEngineSpellcheck::spellCheckLanguages()
+{
+ QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
+ QVERIFY(profile);
+ profile->setSpellCheckLanguages({"en-US","de-DE"});
+ QVERIFY(profile->spellCheckLanguages() == QStringList({"en-US","de-DE"}));
+}
+
+
void tst_QWebEngineSpellcheck::spellCheckEnabled()
{
QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
@@ -127,9 +138,12 @@ void tst_QWebEngineSpellcheck::spellCheckEnabled()
void tst_QWebEngineSpellcheck::spellcheck()
{
+ QFETCH(QStringList, languages);
+ QFETCH(QStringList, suggestions);
+
QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
QVERIFY(profile);
- profile->setSpellCheckLanguage("en-US");
+ profile->setSpellCheckLanguages(languages);
profile->setSpellCheckEnabled(true);
load();
@@ -166,8 +180,7 @@ void tst_QWebEngineSpellcheck::spellcheck()
QVERIFY(m_view->data().misspelledWord() == "lovee");
// check suggestions
- QStringList expected {"love", "loves"};
- QVERIFY(m_view->data().spellCheckerSuggestions() == expected);
+ QVERIFY(m_view->data().spellCheckerSuggestions() == suggestions);
// check replace word
m_view->page()->replaceMisspelledWord("love");
@@ -175,5 +188,13 @@ void tst_QWebEngineSpellcheck::spellcheck()
QTRY_VERIFY(evaluateJavaScriptSync(m_view->page(), "text();").toString() == text);
}
+void tst_QWebEngineSpellcheck::spellcheck_data()
+{
+ QTest::addColumn<QStringList>("languages");
+ QTest::addColumn<QStringList>("suggestions");
+ QTest::newRow("en-US") << QStringList({"en-US"}) << QStringList({"love", "loves"});
+ QTest::newRow("en-US,de-DE") << QStringList({"en-US","de-DE"}) << QStringList({"love", "liebe", "loves"});
+}
+
QTEST_MAIN(tst_QWebEngineSpellcheck)
#include "tst_qwebenginespellcheck.moc"
diff --git a/tests/auto/widgets/qwebengineview/resources/keyboardEvents.html b/tests/auto/widgets/qwebengineview/resources/keyboardEvents.html
new file mode 100644
index 000000000..d536d849f
--- /dev/null
+++ b/tests/auto/widgets/qwebengineview/resources/keyboardEvents.html
@@ -0,0 +1,98 @@
+<html>
+<head>
+ <style>
+ div {
+ width: 300px;
+ margin-bottom: 10px;
+ }
+
+ #div_container {
+ display: inline-block;
+ }
+
+ #div_container div {
+ width: 100px;
+ height: 100px;
+ border: 2px solid black;
+ padding: 10px;
+ margin: 0 10px 0 10px;
+ float: left;
+ }
+
+ #div_container div:focus {
+ border: 2px solid red;
+ }
+
+ #form_container span {
+ display: block;
+ padding-bottom: 10px;
+ }
+
+ #form_container label {
+ float: left;
+ text-align: right;
+ width: 50px;
+ margin-right: 20px;
+ }
+ </style>
+</head>
+
+<body onload="document.getElementById('first_div').focus()">
+ <div id="div_container">
+ <div id="first_div" tabindex="0">First</div>
+ <div id="second_div" tabindex="0">Second</div>
+ </div>
+
+ <div id="form_container">
+ <form><fieldset>
+ <legend>Form</legend>
+
+ <span>
+ <label for="text_input">text</label>
+ <input id="text_input" type="text" />
+ </span>
+
+ <span>
+ <input id="radio1" type="radio" name="radio">radio1</input>
+ <input id="radio2" type="radio" name="radio">radio2</input>
+ </span>
+
+ <span>
+ <input id="checkbox1" type="checkbox" name="checkbox1" checked="true">checkbox1</input>
+ <input id="checkbox2" type="checkbox" name="checkbox2" checked="true">checkbox2</input>
+ </span>
+
+ <span>
+ <label for="number_input">number</label>
+ <input id="number_input" type="number" min="0" max="10" value="5" />
+ </span>
+
+ <span>
+ <label for="range_input">range</label>
+ <input id="range_input" type="range" min="0" max="10" value="5" />
+ </span>
+
+ <span>
+ <label for="search_input">search</label>
+ <input id="search_input" type="search" value="test" />
+ </span>
+
+ <input id="submit_button" type="submit" value="Submit" />
+ </fieldset></form>
+ </div>
+
+ <div>
+ <select id="combobox">
+ <option value="a">a</option>
+ <option value="b">b</option>
+ <option value="c">c</option>
+ </select>
+ </div>
+
+ <div>
+ <a id="first_hyperlink" href="">First</a>
+ <br />
+ <a id="second_hyperlink" href="">Second</a>
+ </div>
+</body>
+</html>
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index 156c56933..9966ad9ee 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -82,6 +82,7 @@ private Q_SLOTS:
void changeLocale();
void inputMethodsTextFormat_data();
void inputMethodsTextFormat();
+ void keyboardEvents();
};
// This will be called before the first test function is executed.
@@ -924,5 +925,94 @@ void tst_QWebEngineView::inputMethodsTextFormat()
QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), string);
}
+void tst_QWebEngineView::keyboardEvents()
+{
+ QWebEngineView view;
+ view.show();
+ QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+ view.load(QUrl("qrc:///resources/keyboardEvents.html"));
+ QVERIFY(loadFinishedSpy.wait());
+
+ QStringList elements;
+ elements << "first_div" << "second_div";
+ elements << "text_input" << "radio1" << "checkbox1" << "checkbox2";
+ elements << "number_input" << "range_input" << "search_input";
+ elements << "submit_button" << "combobox" << "first_hyperlink" << "second_hyperlink";
+
+ // Iterate over the elements of the test page with the Tab key. This tests whether any
+ // element blocks the in-page navigation by Tab.
+ for (const QString &elementId : elements) {
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), elementId);
+ QTest::keyPress(view.focusProxy(), Qt::Key_Tab);
+ }
+
+ // Move back to the radio buttons with the Shift+Tab key combination
+ for (int i = 0; i < 10; ++i)
+ QTest::keyPress(view.focusProxy(), Qt::Key_Tab, Qt::ShiftModifier);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("radio2"));
+
+ // Test the Space key by checking a radio button
+ QVERIFY(!evaluateJavaScriptSync(view.page(), "document.getElementById('radio2').checked").toBool());
+ QTest::keyClick(view.focusProxy(), Qt::Key_Space);
+ QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "document.getElementById('radio2').checked").toBool());
+
+ // Test the Left key by switching the radio button
+ QVERIFY(!evaluateJavaScriptSync(view.page(), "document.getElementById('radio1').checked").toBool());
+ QTest::keyPress(view.focusProxy(), Qt::Key_Left);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("radio1"));
+ QVERIFY(!evaluateJavaScriptSync(view.page(), "document.getElementById('radio2').checked").toBool());
+ QVERIFY(evaluateJavaScriptSync(view.page(), "document.getElementById('radio1').checked").toBool());
+
+ // Test the Space key by unchecking a checkbox
+ evaluateJavaScriptSync(view.page(), "document.getElementById('checkbox1').focus()");
+ QVERIFY(evaluateJavaScriptSync(view.page(), "document.getElementById('checkbox1').checked").toBool());
+ QTest::keyClick(view.focusProxy(), Qt::Key_Space);
+ QTRY_VERIFY(!evaluateJavaScriptSync(view.page(), "document.getElementById('checkbox1').checked").toBool());
+
+ // Test the Up and Down keys by changing the value of a spinbox
+ evaluateJavaScriptSync(view.page(), "document.getElementById('number_input').focus()");
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('number_input').value").toInt(), 5);
+ QTest::keyPress(view.focusProxy(), Qt::Key_Up);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('number_input').value").toInt(), 6);
+ QTest::keyPress(view.focusProxy(), Qt::Key_Down);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('number_input').value").toInt(), 5);
+
+ // Test the Left, Right, Home, PageUp, End and PageDown keys by changing the value of a slider
+ evaluateJavaScriptSync(view.page(), "document.getElementById('range_input').focus()");
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('range_input').value").toString(), QStringLiteral("5"));
+ QTest::keyPress(view.focusProxy(), Qt::Key_Left);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('range_input').value").toString(), QStringLiteral("4"));
+ QTest::keyPress(view.focusProxy(), Qt::Key_Right);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('range_input').value").toString(), QStringLiteral("5"));
+ QTest::keyPress(view.focusProxy(), Qt::Key_Home);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('range_input').value").toString(), QStringLiteral("0"));
+ QTest::keyPress(view.focusProxy(), Qt::Key_PageUp);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('range_input').value").toString(), QStringLiteral("1"));
+ QTest::keyPress(view.focusProxy(), Qt::Key_End);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('range_input').value").toString(), QStringLiteral("10"));
+ QTest::keyPress(view.focusProxy(), Qt::Key_PageDown);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('range_input').value").toString(), QStringLiteral("9"));
+
+ // Test the Escape key by removing the content of a search field
+ evaluateJavaScriptSync(view.page(), "document.getElementById('search_input').focus()");
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('search_input').value").toString(), QStringLiteral("test"));
+ QTest::keyPress(view.focusProxy(), Qt::Key_Escape);
+ QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "document.getElementById('search_input').value").toString().isEmpty());
+
+ // Test the alpha keys by changing the values in a combobox
+ evaluateJavaScriptSync(view.page(), "document.getElementById('combobox').focus()");
+ QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('combobox').value").toString(), QStringLiteral("a"));
+ QTest::keyPress(view.focusProxy(), Qt::Key_B);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('combobox').value").toString(), QStringLiteral("b"));
+ // Must wait with the second key press to simulate selection of another element
+ QTest::keyPress(view.focusProxy(), Qt::Key_C, Qt::NoModifier, 1000);
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('combobox').value").toString(), QStringLiteral("c"));
+
+ // Test the Enter key by loading a page with a hyperlink
+ evaluateJavaScriptSync(view.page(), "document.getElementById('first_hyperlink').focus()");
+ QTest::keyPress(view.focusProxy(), Qt::Key_Enter);
+ QVERIFY(loadFinishedSpy.wait());
+}
+
QTEST_MAIN(tst_QWebEngineView)
#include "tst_qwebengineview.moc"
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.qrc b/tests/auto/widgets/qwebengineview/tst_qwebengineview.qrc
index b32b533c2..4809bbebf 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.qrc
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.qrc
@@ -5,5 +5,6 @@
<file>resources/input_types.html</file>
<file>resources/scrolltest_page.html</file>
<file>resources/basic_printing_page.html</file>
+ <file>resources/keyboardEvents.html</file>
</qresource>
</RCC>
diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro
index 2f5416701..c7096b6b6 100644
--- a/tests/auto/widgets/widgets.pro
+++ b/tests/auto/widgets/widgets.pro
@@ -13,7 +13,10 @@ SUBDIRS += \
qwebenginesettings \
qwebengineview
-# QTBUG-53135, osx does not use hunspell
-!contains(WEBENGINE_CONFIG, no_spellcheck):!osx:!cross_compile {
- SUBDIRS += qwebenginespellcheck
+!contains(WEBENGINE_CONFIG, use_spellchecker):!cross_compile {
+ !contains(WEBENGINE_CONFIG, use_native_spellchecker) {
+ SUBDIRS += qwebenginespellcheck
+ } else {
+ message("Spellcheck test will not be built because it depends on usage of Hunspell dictionaries.")
+ }
}
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index 16f56dbe9..edf95846c 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -1,6 +1,7 @@
TEMPLATE = subdirs
SUBDIRS += \
- widgets
+ widgets \
+ quick
!qtHaveModule(webenginewidgets): SUBDIRS -= widgets
diff --git a/tests/manual/quick/faviconbrowser/AddressBar.qml b/tests/manual/quick/faviconbrowser/AddressBar.qml
new file mode 100644
index 000000000..7122b2862
--- /dev/null
+++ b/tests/manual/quick/faviconbrowser/AddressBar.qml
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+
+Rectangle {
+ id: root
+
+ property int progress: 0
+ property url iconUrl: ""
+ property url pageUrl: ""
+
+ signal accepted(url addressUrl)
+
+ clip: true
+
+ onActiveFocusChanged: {
+ if (activeFocus)
+ addressField.forceActiveFocus();
+ }
+
+ Rectangle {
+ width: addressField.width / 100 * root.progress
+ height: root.height
+
+ visible: root.progress < 100
+
+ color: "#b6dca6"
+ radius: root.radius
+ }
+
+ TextField {
+ id: addressField
+ anchors.fill: parent
+
+ Image {
+ anchors.verticalCenter: addressField.verticalCenter
+ x: 5; z: parent.z + 1
+ width: 16; height: 16
+ sourceSize: Qt.size(width, height)
+ source: root.iconUrl
+ visible: root.progress == 100
+ }
+
+ Text {
+ text: root.progress < 0 ? "" : root.progress + "%"
+ x: 5; z: parent.z + 1
+ font.bold: true
+ anchors.verticalCenter: parent.verticalCenter
+
+ visible: root.progress < 100
+ }
+
+ style: TextFieldStyle {
+ padding.left: 30
+
+ background: Rectangle {
+ color: "transparent"
+ border.color: "black"
+ border.width: 1
+ radius: root.radius
+ }
+ }
+
+ onActiveFocusChanged: {
+ if (activeFocus)
+ selectAll();
+ else
+ deselect();
+ }
+
+ text: root.pageUrl
+ onAccepted: root.accepted(utils.fromUserInput(text))
+ }
+}
diff --git a/tests/manual/quick/faviconbrowser/FaviconPanel.qml b/tests/manual/quick/faviconbrowser/FaviconPanel.qml
new file mode 100644
index 000000000..ce768b82d
--- /dev/null
+++ b/tests/manual/quick/faviconbrowser/FaviconPanel.qml
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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
+import QtQuick.Controls 1.4
+import QtQuick.Controls.Styles 1.4
+import QtQuick.Layouts 1.1
+
+Item {
+ id: root
+
+ property url iconUrl: ""
+ property int iconSize: 128
+ property int iconMinimumSize: 8
+ property int iconMaximumSize: 256
+
+ RowLayout {
+ anchors.fill: parent
+ spacing: 2
+
+ Rectangle {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ RowLayout {
+ anchors.fill: parent
+ spacing: 2
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.preferredWidth: (parent.width - 2 * parent.spacing) / 3
+
+ border.color: "black"
+ border.width: 1
+ clip: true
+
+ Text {
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ font.bold: true
+
+ text: "faviconImage"
+ }
+
+ Image {
+ id: faviconImage
+ anchors.centerIn: parent
+
+ width: root.iconSize
+ height: width
+ sourceSize: Qt.size(width, height)
+
+ source: root.iconUrl
+
+ onStatusChanged: {
+ if (status == Image.Ready) {
+ grabToImage(function(result) {
+ grabImage.source = result.url;
+ });
+ }
+
+ if (status == Image.Null)
+ grabImage.source = "";
+ }
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.preferredWidth: (parent.width - 2 * parent.spacing) / 3
+
+ border.color: "black"
+ border.width: 1
+ clip: true
+
+ Text {
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ font.bold: true
+
+ text: "grabImage"
+ }
+
+ Image {
+ id: grabImage
+ anchors.centerIn: parent
+
+ width: root.iconSize
+ height: width
+
+ onStatusChanged: {
+ if (status == Image.Ready || status == Image.Null)
+ faviconCanvas.requestPaint();
+ }
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.preferredWidth: (parent.width - 2 * parent.spacing) / 3
+
+ border.color: "black"
+ border.width: 1
+ clip: true
+
+ Text {
+ z: parent.z + 1
+ anchors.top: parent.top
+ anchors.topMargin: 5
+ anchors.left: parent.left
+ anchors.leftMargin: 5
+ font.bold: true
+
+ text: "faviconCanvas"
+ }
+
+ Canvas {
+ id: faviconCanvas
+ anchors.centerIn: parent
+
+ width: root.iconSize
+ height: width
+
+ onPaint: {
+ var ctx = getContext("2d");
+ ctx.reset();
+ ctx.clearRect(0, 0, width, height);
+
+ if (grabImage.source == "")
+ return;
+
+ ctx.drawImage(grabImage, 0, 0, width, height);
+
+ var imageData = ctx.getImageData(width/2, height/2, width/2, height/2);
+ var pixel = imageData.data;
+
+ verbose.append("pixel(" + width/2 + ", " + height/2 + "): " + pixel[0] + ", " + pixel[1] + ", " + pixel[2]);
+ }
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.preferredWidth: 100
+
+ Slider {
+ id: faviconSizeSlider
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.top: parent.top
+ anchors.bottom: faviconSizeSpin.top
+
+ orientation: Qt.Vertical
+ minimumValue: root.iconMinimumSize
+ maximumValue: root.iconMaximumSize
+ stepSize: 1
+ tickmarksEnabled: true
+ value: root.iconSize
+
+ onValueChanged: {
+ if (pressed && value != root.iconSize)
+ root.iconSize = value;
+ }
+ }
+
+ SpinBox {
+ id: faviconSizeSpin
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+
+ minimumValue: root.iconMinimumSize
+ maximumValue: root.iconMaximumSize
+ value: root.iconSize
+
+ onEditingFinished: {
+ if (value != root.iconSize)
+ root.iconSize = value;
+ }
+ }
+ }
+
+ TextArea {
+ id: verbose
+
+ Layout.fillHeight: true
+ Layout.preferredWidth: 310
+
+ readOnly: true
+ tabChangesFocus: true
+
+ font.family: "Monospace"
+ font.pointSize: 12
+
+ textFormat: TextEdit.RichText
+ frameVisible: false
+
+ style: TextAreaStyle {
+ backgroundColor: "lightgray"
+ }
+ }
+ }
+}
diff --git a/tests/manual/quick/faviconbrowser/faviconbrowser.pro b/tests/manual/quick/faviconbrowser/faviconbrowser.pro
new file mode 100644
index 000000000..d4368ab3e
--- /dev/null
+++ b/tests/manual/quick/faviconbrowser/faviconbrowser.pro
@@ -0,0 +1,23 @@
+QT += qml quick webengine
+qtHaveModule(widgets) {
+ QT += widgets # QApplication is required to get native styling with QtQuickControls
+}
+
+TARGET = faviconbrowser
+TEMPLATE = app
+
+
+SOURCES = \
+ main.cpp
+
+HEADERS = \
+ utils.h
+
+OTHER_FILES += \
+ main.qml \
+ AddressBar.qml \
+ FaviconPanel.qml
+
+RESOURCES += \
+ faviconbrowser.qrc
+
diff --git a/tests/manual/quick/faviconbrowser/faviconbrowser.qrc b/tests/manual/quick/faviconbrowser/faviconbrowser.qrc
new file mode 100644
index 000000000..95d0dc2c4
--- /dev/null
+++ b/tests/manual/quick/faviconbrowser/faviconbrowser.qrc
@@ -0,0 +1,17 @@
+<!DOCTYPE RCC><RCC version="1.0">
+ <qresource prefix="/">
+ <file>main.qml</file>
+ <file>AddressBar.qml</file>
+ <file>FaviconPanel.qml</file>
+ </qresource>
+ <qresource prefix="test">
+ <file alias="favicon-multi-gray.html">../../../auto/quick/qmltests/data/favicon-multi-gray.html</file>
+ <file alias="favicon-candidates-gray.html">../../../auto/quick/qmltests/data/favicon-candidates-gray.html</file>
+ <file alias="icons/grayicons.ico">../../../auto/quick/qmltests/data/icons/grayicons.ico</file>
+ <file alias="icons/gray16.png">../../../auto/quick/qmltests/data/icons/gray16.png</file>
+ <file alias="icons/gray32.png">../../../auto/quick/qmltests/data/icons/gray32.png</file>
+ <file alias="icons/gray64.png">../../../auto/quick/qmltests/data/icons/gray64.png</file>
+ <file alias="icons/gray128.png">../../../auto/quick/qmltests/data/icons/gray128.png</file>
+ <file alias="icons/gray255.png">../../../auto/quick/qmltests/data/icons/gray255.png</file>
+ </qresource>
+</RCC>
diff --git a/tests/manual/quick/faviconbrowser/main.cpp b/tests/manual/quick/faviconbrowser/main.cpp
new file mode 100644
index 000000000..b75be2483
--- /dev/null
+++ b/tests/manual/quick/faviconbrowser/main.cpp
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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$
+**
+****************************************************************************/
+
+#include "utils.h"
+
+#ifndef QT_NO_WIDGETS
+#include <QtWidgets/QApplication>
+typedef QApplication Application;
+#else
+#include <QtGui/QGuiApplication>
+typedef QGuiApplication Application;
+#endif
+#include <QtQml/QQmlApplicationEngine>
+#include <QtQml/QQmlContext>
+#include <QtWebEngine/qtwebengineglobal.h>
+
+int main(int argc, char **argv)
+{
+ Application app(argc, argv);
+
+ QtWebEngine::initialize();
+
+ QQmlApplicationEngine appEngine;
+ Utils utils;
+ appEngine.rootContext()->setContextProperty("utils", &utils);
+ appEngine.load(QUrl("qrc:/main.qml"));
+
+ return app.exec();
+}
diff --git a/tests/manual/quick/faviconbrowser/main.qml b/tests/manual/quick/faviconbrowser/main.qml
new file mode 100644
index 000000000..1ad5fc2e8
--- /dev/null
+++ b/tests/manual/quick/faviconbrowser/main.qml
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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
+import QtQuick.Controls 1.4
+import QtQuick.Layouts 1.1
+import QtWebEngine 1.3
+import Qt.labs.settings 1.0
+
+ApplicationWindow {
+ width: 1300
+ height: 900
+ visible: true
+
+ Item {
+ id: bookmarkUrls
+
+ property url multiTest: Qt.resolvedUrl("qrc:/test/favicon-multi-gray.html")
+ property url candidatesTest: Qt.resolvedUrl("qrc:/test/favicon-candidates-gray.html")
+ property url aboutBlank: Qt.resolvedUrl("about:blank")
+ property url qtHome: Qt.resolvedUrl("http://www.qt.io/")
+ }
+
+ Settings {
+ id: appSettings
+
+ property alias autoLoadIconsForPage: autoLoadIconsForPage.checked
+ property alias touchIconsEnabled: touchIconsEnabled.checked
+ }
+
+ SplitView {
+ anchors.fill: parent
+ orientation: Qt.Vertical
+
+ FaviconPanel {
+ id: faviconPanel
+
+ Layout.fillWidth: true
+ Layout.minimumHeight: 200
+
+ Layout.margins: 2
+
+ iconUrl: webEngineView && webEngineView.icon
+ }
+
+ ColumnLayout {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.topMargin: 2
+
+ AddressBar {
+ id: addressBar
+
+ Layout.fillWidth: true
+ Layout.leftMargin: 5
+ Layout.rightMargin: 5
+ height: 25
+
+ color: "white"
+ radius: 4
+
+ progress: webEngineView && webEngineView.loadProgress
+ iconUrl: webEngineView && webEngineView.icon
+ pageUrl: webEngineView && webEngineView.url
+
+ onAccepted: webEngineView.url = addressUrl
+ }
+
+ Rectangle {
+ id: toolBar
+
+ Layout.fillWidth: true
+ Layout.leftMargin: 5
+ Layout.rightMargin: 5
+ Layout.preferredHeight: 25
+
+ RowLayout {
+ anchors.verticalCenter: parent.verticalCenter
+
+ Button {
+ text: "Multi-sized Favicon Test"
+ onClicked: webEngineView.url = bookmarkUrls.multiTest
+ enabled: webEngineView.url != bookmarkUrls.multiTest
+ }
+
+ Button {
+ text: "Candidate Favicons Test"
+ onClicked: webEngineView.url = bookmarkUrls.candidatesTest
+ enabled: webEngineView.url != bookmarkUrls.candidatesTest
+ }
+
+ Button {
+ text: "About Blank"
+ onClicked: webEngineView.url = bookmarkUrls.aboutBlank
+ enabled: webEngineView.url != bookmarkUrls.aboutBlank
+ }
+
+ Button {
+ text: "Qt Home Page"
+ onClicked: webEngineView.url = bookmarkUrls.qtHome
+ enabled: webEngineView.url != bookmarkUrls.qtHome
+ }
+ }
+
+ ToolButton {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+
+ menu: Menu {
+ MenuItem {
+ id: autoLoadIconsForPage
+ text: "Icons On"
+ checkable: true
+ checked: WebEngine.settings.autoLoadIconsForPage
+
+ onCheckedChanged: webEngineView.reload()
+ }
+
+ MenuItem {
+ id: touchIconsEnabled
+ text: "Touch Icons On"
+ checkable: true
+ checked: WebEngine.settings.touchIconsEnabled
+ enabled: autoLoadIconsForPage.checked
+
+ onCheckedChanged: webEngineView.reload()
+ }
+ }
+ }
+ }
+
+ WebEngineView {
+ id: webEngineView
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ settings.autoLoadIconsForPage: appSettings.autoLoadIconsForPage
+ settings.touchIconsEnabled: appSettings.touchIconsEnabled
+
+ Component.onCompleted: webEngineView.url = bookmarkUrls.multiTest
+ }
+ }
+ }
+}
diff --git a/tests/manual/quick/faviconbrowser/utils.h b/tests/manual/quick/faviconbrowser/utils.h
new file mode 100644
index 000000000..79aa38cc7
--- /dev/null
+++ b/tests/manual/quick/faviconbrowser/utils.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, 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$
+**
+****************************************************************************/
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <QtCore/QFileInfo>
+#include <QtCore/QUrl>
+
+class Utils : public QObject {
+ Q_OBJECT
+public:
+ Q_INVOKABLE static QUrl fromUserInput(const QString& userInput);
+};
+
+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/manual/quick/quick.pro b/tests/manual/quick/quick.pro
new file mode 100644
index 000000000..5251c4b42
--- /dev/null
+++ b/tests/manual/quick/quick.pro
@@ -0,0 +1,4 @@
+TEMPLATE = subdirs
+
+SUBDIRS += \
+ faviconbrowser
diff --git a/tools/about_credits_entry.tmpl b/tools/about_credits_entry.tmpl
index dd74c880a..20bbb28a0 100644
--- a/tools/about_credits_entry.tmpl
+++ b/tools/about_credits_entry.tmpl
@@ -1,6 +1,6 @@
/*!
\contentspage qtwebengine-licensing.html
-\page qtwebengine-3rdparty-{{name-sanitized}}.html
+\page qtwebengine-3rdparty-{{name-sanitized}}.html attribution
\ingroup qtwebengine-licensing
\brief {{license-type}}
\title {{name}}
diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf
index 89fa3a242..c6f07e39d 100644
--- a/tools/qmake/mkspecs/features/configure.prf
+++ b/tools/qmake/mkspecs/features/configure.prf
@@ -28,40 +28,62 @@ defineTest(runConfigure) {
!cross_compile: qtConfig(xcb): REQUIRED_PACKAGES += libdrm xcomposite xcursor xi xrandr xscrnsaver xtst
contains(QT_CONFIG, pulseaudio): REQUIRED_PACKAGES += libpulse
qtConfig(system-png): REQUIRED_PACKAGES += libpng
- qtConfig(system-harfbuzz): REQUIRED_PACKAGES += harfbuzz
+ qtConfig(system-harfbuzz) {
+ packagesExist("\'harfbuzz >= 1.2.0\'"): WEBENGINE_CONFIG += use_system_harfbuzz
+ else: log("System harfbuzz is too old (min. version 1.2). Using Chromium's copy.$${EOL}")
+ }
!cross_compile: REQUIRED_PACKAGES += libpci
for(package, $$list($$REQUIRED_PACKAGES)) {
!packagesExist($$package):skipBuild("Unmet dependency: $$package")
}
- packagesExist(minizip, zlib): WEBENGINE_CONFIG += use_system_minizip
+ packagesExist(minizip, zlib): WEBENGINE_CONFIG += use_system_minizip use_system_zlib
else: log("System zlib or minizip not found. Using Chromium's copies.$${EOL}")
- packagesExist(libwebp,libwebpdemux): WEBENGINE_CONFIG += use_system_libwebp
+ packagesExist(libwebp,libwebpdemux): WEBENGINE_CONFIG += use_system_libwebp use_system_libwebpdemux
else: log("System libwebp or libwebpdemux not found. Using Chromium's copies.$${EOL}")
- packagesExist(libxml-2.0,libxslt): WEBENGINE_CONFIG += use_system_libxslt
+ packagesExist(libxml-2.0,libxslt): WEBENGINE_CONFIG += use_system_libxslt use_system_libxml2
else: log("System libxml2 or libxslt not found. Using Chromium's copies.$${EOL}")
for(package, $$list("libevent jsoncpp opus protobuf")) {
packagesExist($$package): WEBENGINE_CONFIG += use_system_$$package
- else: log("System $$package not found. Using Chromium's copy.$${EOL}")
+ else {
+ log("System $$package not found. Using Chromium's copy.$${EOL}")
+ WEBENGINE_CONFIG += use_bundled_$$package
+ }
}
use?(system_protobuf) {
!system("which protoc > /dev/null") {
log("Protobuf compiler not found. Using Chromium's copy of protobuf.$${EOL}")
WEBENGINE_CONFIG -= use_system_protobuf
+ WEBENGINE_CONFIG += use_bundled_protobuf
}
}
config_libvpx: WEBENGINE_CONFIG += use_system_vpx
- else: log("Compatible system libvpx not found. Using Chromium's copy.$${EOL}")
+ else {
+ log("Compatible system libvpx not found. Using Chromium's copy.$${EOL}")
+ WEBENGINE_CONFIG += use_bundled_libvpx
+ }
config_srtp: WEBENGINE_CONFIG += use_system_libsrtp
- else: log("System libsrtp not found. Using Chromium's copy.$${EOL}")
+ else {
+ log("System libsrtp not found. Using Chromium's copy.$${EOL}")
+ WEBENGINE_CONFIG += use_bundled_srtp
+ }
config_snappy: WEBENGINE_CONFIG += use_system_snappy
- else: log("System snappy not found. Using Chromium's copy.$${EOL}")
+ else {
+ log("System snappy not found. Using Chromium's copy.$${EOL}")
+ WEBENGINE_CONFIG += use_bundled_snappy
+ }
!cross_compile {
packagesExist(nss): WEBENGINE_CONFIG += use_nss
else: log("System NSS not found, BoringSSL will be used.$${EOL}")
}
}
+ isQtMinimum(5, 8) {
+ include($$QTWEBENGINE_OUT_ROOT/qtwebengine-config.pri)
+ QT_FOR_CONFIG += webengine-private
+ qtConfig(proprietary-codecs): WEBENGINE_CONFIG += use_proprietary_codecs
+ qtConfig(spellchecker): WEBENGINE_CONFIG += use_spellchecker
+ }
isEmpty(skipBuildReason): {
cache(CONFIG, add, $$list(webengine_successfully_configured))
@@ -70,61 +92,80 @@ defineTest(runConfigure) {
export(WEBENGINE_CONFIG)
}
}
-}
-# This is called from default_post, at which point we've also parsed
-# command line options
-defineTest(finalizeConfigure) {
- linux {
- use?(nss) {
- log("Certificate handling.............. Using system NSS$${EOL}")
- } else {
- log("Certificate handling.............. Using bundled BoringSSL$${EOL}")
- }
+ unix:!darwin {
+ log("System library dependencies:$${EOL}")
use?(system_icu) {
packagesExist("icu-uc icu-i18n") {
- log("ICU............................... Using system version$${EOL}")
+ log(" ICU ................................ Using system version$${EOL}")
} else {
- log("ICU............................... System ICU not found$${EOL}")
+ log(" ICU ................................ System ICU not found$${EOL}")
skipBuild("Unmet dependencies: icu-uc, icu-i18n")
}
} else {
- log("ICU............................... Using internal copy (Default, force system ICU with WEBENGINE_CONFIG+=use_system_icu)$${EOL}")
+ log(" ICU ................................ Using internal copy (Default, force system ICU with WEBENGINE_CONFIG+=use_system_icu)$${EOL}")
+ WEBENGINE_CONFIG += use_bundled_icu
}
use?(system_ffmpeg) {
packagesExist("libavcodec libavformat libavutil") {
packagesExist("libwebp, libwebpdemux, opus, \'vpx >= 1.4\'"){
- log("FFMPEG............................ Using system version$${EOL}")
+ log(" FFMPEG ............................. Using system version$${EOL}")
} else {
- log("FFMPEG............................ Conflicting FFMPEG dependencies$${EOL}")
+ log(" FFMPEG ............................. Conflicting FFMPEG dependencies$${EOL}")
skipBuild("Unmet dependencies: opus, vpx, libwebp, libwebpdemux")
}
} else {
- log("FFMPEG............................ System FFMPEG not found$${EOL}")
+ log(" FFMPEG ............................. System FFMPEG not found$${EOL}")
skipBuild("Unmet dependencies: libavcodec, libavformat, libavutil")
}
} else {
- log("FFMPEG............................ Using internal copy (Default, force system FFMPEG with WEBENGINE_CONFIG+=use_system_ffmpeg)$${EOL}")
+ log(" FFMPEG ............................. Using internal copy (Default, force system FFMPEG with WEBENGINE_CONFIG+=use_system_ffmpeg)$${EOL}")
+ WEBENGINE_CONFIG += use_bundled_ffmpeg
}
+ for(config, WEBENGINE_CONFIG) {
+ match = $$find(config, "^use_system_")
+ !isEmpty(match) {
+ use_system += $$replace(match, ^use_system_,)
+ }
+ match = $$find(config, "^use_bundled_")
+ !isEmpty(match) {
+ use_bundled += $$replace(match, ^use_bundled_,)
+ }
+ }
+ !isEmpty(use_system): log(" Optional system libraries used ..... $$use_system$${EOL}")
+ !isEmpty(use_bundled): log(" Optional bundled libraries used .... $$use_bundled$${EOL}")
}
+ log("Configurable features:$${EOL}")
use?(proprietary_codecs) {
- log("Proprietary codecs (H264, MP3).... Enabled$${EOL}")
+ log(" Proprietary codecs (H264, MP3) ..... Enabled$${EOL}")
} else {
- log("Proprietary codecs (H264, MP3).... Not enabled (Default, enable with WEBENGINE_CONFIG+=use_proprietary_codecs)$${EOL}")
+ log(" Proprietary codecs (H264, MP3) ..... Not enabled (Default, enable with WEBENGINE_CONFIG+=use_proprietary_codecs)$${EOL}")
}
qtHaveModule(positioning): {
- log("Geolocation....................... Enabled$${EOL}")
+ log(" Geolocation ........................ Enabled$${EOL}")
} else {
- log("Geolocation....................... Not enabled (Requires Qt Positioning module)$${EOL}")
+ log(" Geolocation ........................ Not enabled (Requires Qt Positioning module)$${EOL}")
+ }
+ unix:!darwin {
+ use?(nss) {
+ log(" Certificate handling ............... Using system NSS$${EOL}")
+ } else {
+ log(" Certificate handling ............... Using bundled BoringSSL$${EOL}")
+ }
}
osx {
use?(appstore_compliant_code) {
- log("AppStore Compliant ............... Enabled$${EOL}")
+ log(" Mac App Store Compliant ............ Enabled$${EOL}")
+ } else {
+ log(" Mac App Store Compliant ............ Not enabled (Default, enable with WEBENGINE_CONFIG+=use_appstore_compliant_code)$${EOL}")
+ }
+ use?(native_spellchecker) {
+ log("Native Spellchecker .............. Enabled$${EOL}")
} else {
- log("AppStore Compliant ............... Not enabled (Default, enable with WEBENGINE_CONFIG+=use_appstore_compliant_code)$${EOL}")
+ log("Native Spellchecker .............. Not enabled (Default, enable with WEBENGINE_CONFIG+=use_native_spellchecker)$${EOL}")
}
!isMinOSXSDKVersion(10, 10, 3) {
- log("Force Touch API usage ............ Not enabled (Because the OS X SDK version to be used \"$${WEBENGINE_OSX_SDK_PRODUCT_VERSION}\" is lower than the required \"10.10.3\")$${EOL}")
+ log(" Force Touch API usage .............. Not enabled (Because the OS X SDK version to be used \"$${WEBENGINE_OSX_SDK_PRODUCT_VERSION}\" is lower than the required \"10.10.3\")$${EOL}")
}
}
}
diff --git a/tools/qmake/mkspecs/features/default_post.prf b/tools/qmake/mkspecs/features/default_post.prf
deleted file mode 100644
index 64e8cb1fe..000000000
--- a/tools/qmake/mkspecs/features/default_post.prf
+++ /dev/null
@@ -1,11 +0,0 @@
-load(default_post)
-load(functions)
-
-root_project_file:isPlatformSupported(): finalizeConfigure()
-
-!isEmpty(skipBuildReason) {
- SUBDIRS =
- export(SUBDIRS)
- log($${skipBuildReason}$${EOL})
- log(QtWebEngine will not be built.$${EOL})
-}
diff --git a/tools/qmake/mkspecs/features/default_pre.prf b/tools/qmake/mkspecs/features/default_pre.prf
index 27aded013..77e437bc9 100644
--- a/tools/qmake/mkspecs/features/default_pre.prf
+++ b/tools/qmake/mkspecs/features/default_pre.prf
@@ -1,6 +1,3 @@
-# Resolve root directories for sources
-QTWEBENGINE_ROOT = $$replace(PWD, /tools/qmake/mkspecs/features$,)
-
# We depend on libc++ to build chromium so our macosx-version-min has to be 10.7
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.7
@@ -24,14 +21,3 @@ EOL = $$escape_expand(\\n)
# Call the original default_pre.
load(default_pre)
load(functions)
-
-# Check platform support and run config tests early enough to bail
-equals(_PRO_FILE_, "$$QTWEBENGINE_ROOT/qtwebengine.pro"): CONFIG += root_project_file
-
-root_project_file:isPlatformSupported() {
- !exists($$QTWEBENGINE_ROOT/src/3rdparty/chromium) {
- error("Submodule qtwebengine-chromium does not exist. Run 'git submodule update --init'.")
- }
- load(configure)
- runConfigure()
-}
diff --git a/tools/qmake/mkspecs/features/functions.prf b/tools/qmake/mkspecs/features/functions.prf
index d109e2859..6ee9be57d 100644
--- a/tools/qmake/mkspecs/features/functions.prf
+++ b/tools/qmake/mkspecs/features/functions.prf
@@ -43,14 +43,14 @@ defineTest(isPlatformSupported) {
return(false)
}
} else:osx {
- lessThan(QMAKE_XCODE_VERSION, 6.3) {
- skipBuild("Using XCode version $$QMAKE_XCODE_VERSION, but at least version 6.3 is required to build Qt WebEngine.")
+ lessThan(QMAKE_XCODE_VERSION, 5.1) {
+ skipBuild("Using XCode version $$QMAKE_XCODE_VERSION, but at least version 5.1 is required to build Qt WebEngine.")
return(false)
}
- # We require OS X 10.10 (darwin version 14.0.0) or newer
+ # We require OS X 10.9 (darwin version 13.0.0) or newer
darwin_major_version = $$section(QMAKE_HOST.version, ., 0, 0)
- lessThan(darwin_major_version, 14) {
- skipBuild("Qt WebEngine requires OS X version 10.10 or newer.")
+ lessThan(darwin_major_version, 13) {
+ skipBuild("Qt WebEngine requires OS X version 10.9 or newer.")
return(false)
}
!isMinOSXSDKVersion(10, 10): {
@@ -75,9 +75,20 @@ defineTest(isPlatformSupported) {
return(false)
}
!isPythonVersionSupported(): return(false)
+ !isArchSupported(): return(false)
+ isSanitizerEnabled():!isSanitizerSupported():!forceSanitizerBuild(): return(false)
return(true)
}
+defineTest(isArchSupported) {
+ contains(QT_ARCH, "i386")|contains(QT_ARCH, "x86_64"): return(true)
+ contains(QT_ARCH, "arm")|contains(QT_ARCH, "arm64"): return(true)
+ contains(QT_ARCH, "mips")|contains(QT_ARCH, "mips64"): return(true)
+
+ skipBuild("QtWebEngine can only be built for x86, x86-64, ARM, Aarch64, MIPSel, and MIPS64 architectures.")
+ return(false)
+}
+
defineTest(isPythonVersionSupported) {
python_error_msg = "Python version 2 (2.7.5 or later) is required to build Qt WebEngine."
python_version = $$system('python -c "import sys; print(sys.version_info[0:3])"')
@@ -97,6 +108,106 @@ defineTest(isPythonVersionSupported) {
return(false)
}
+defineTest(isSanitizerEnabled) {
+ sanitize_address|sanitize_memory|sanitize_undefined|sanitize_thread: return(true)
+ return(false)
+}
+
+defineTest(forceSanitizerBuild) {
+ contains(WEBENGINE_CONFIG, force_sanitizer_build): return(true)
+ skipBuild("Chosen sanitizer configuration is not supported. Use WEBENGINE_CONFIG+=force_sanitizer_build to force build with the chosen sanitizer configuration.")
+ return(false)
+}
+
+defineTest(isSanitizerSupported) {
+ sanitizer_combo_supported = true
+ sanitize_address {
+ asan_supported = false
+ linux-clang-libc++:isSanitizerSupportedOnLinux() {
+ asan_supported = true
+ } else:macos:isSanitizerSupportedOnMacOS() {
+ asan_supported = true
+ }
+ !$$asan_supported {
+ sanitizer_combo_supported = false
+ warning("An address sanitizer-enabled Qt WebEngine build can only be built on Linux or macOS using Clang and libc++.")
+ }
+ }
+
+ sanitize_memory {
+ sanitizer_combo_supported = false
+ warning("A memory sanitizer-enabled Qt WebEngine build is not supported.")
+ }
+
+ sanitize_undefined {
+ ubsan_supported = false
+ linux-clang-libc++:isSanitizerSupportedOnLinux():CONFIG(release, debug|release):!debug_and_release {
+ ubsan_supported = true
+ }
+ !$$ubsan_supported {
+ sanitizer_combo_supported = false
+ warning("An undefined behavior sanitizer-enabled Qt WebEngine build can only be built on Linux using Clang and libc++ in release mode.")
+ }
+ }
+
+ sanitize_thread {
+ tsan_supported = false
+ linux-clang-libc++:isSanitizerSupportedOnLinux() {
+ tsan_supported = true
+ }
+ !$$tsan_supported {
+ sanitizer_combo_supported = false
+ warning("A thread sanitizer-enabled Qt WebEngine build can only be built on Linux using Clang and libc++.")
+ }
+ }
+
+ $$sanitizer_combo_supported: return(true)
+ return(false)
+}
+
+defineTest(isSanitizerSupportedOnLinux) {
+ isSanitizerLinuxClangVersionSupported(): return(true)
+ return(false)
+}
+
+defineTest(isSanitizerSupportedOnMacOS) {
+ isEmpty(QT_APPLE_CLANG_MAJOR_VERSION) {
+ QTWEBENGINE_CLANG_IS_APPLE = false
+ } else {
+ QTWEBENGINE_CLANG_IS_APPLE = true
+ }
+ $$QTWEBENGINE_CLANG_IS_APPLE:isSanitizerMacOSAppleClangVersionSupported(): return(true)
+ else:isSanitizerMacOSClangVersionSupported(): return(true)
+ return(false)
+}
+
+defineTest(isSanitizerMacOSAppleClangVersionSupported) {
+ # Clang sanitizer suppression attributes work from Apple Clang version 7.3.0+.
+ greaterThan(QT_APPLE_CLANG_MAJOR_VERSION, 7): return(true)
+ greaterThan(QT_APPLE_CLANG_MINOR_VERSION, 2): return(true)
+
+ warning("Using Apple Clang version $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}.$${QT_APPLE_CLANG_PATCH_VERSION}, but at least Apple Clang version 7.3.0 is required to build a sanitizer-enabled Qt WebEngine.")
+ return(false)
+}
+
+defineTest(isSanitizerMacOSClangVersionSupported) {
+ # Clang sanitizer suppression attributes work from non-apple Clang version 3.7+.
+ greaterThan(QT_CLANG_MAJOR_VERSION, 3): return(true)
+ greaterThan(QT_CLANG_MINOR_VERSION, 6): return(true)
+
+ warning("Using Clang version $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}, but at least Clang version 3.7 is required to build a sanitizer-enabled Qt WebEngine.")
+ return(false)
+}
+
+defineTest(isSanitizerLinuxClangVersionSupported) {
+ # Clang sanitizer suppression attributes work from Clang version 3.7+.
+ greaterThan(QT_CLANG_MAJOR_VERSION, 3): return(true)
+ greaterThan(QT_CLANG_MINOR_VERSION, 6): return(true)
+
+ warning("Using Clang version $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}, but at least Clang version 3.7 is required to build a sanitizer-enabled Qt WebEngine.")
+ return(false)
+}
+
defineTest(isGCCVersionSupported) {
# The below will work for gcc 4.7 and up and also match gcc 5
greaterThan(QT_GCC_MINOR_VERSION, 6):return(true)
@@ -264,28 +375,17 @@ defineReplace(findOrBuildNinja) {
!exists($$out) {
src_3rd_party_dir = $$absolute_path("$${getChromiumSrcDir()}/../", "$$QTWEBENGINE_ROOT")
- out = $$shadowed($$absolute_path("ninja/ninja", "$$src_3rd_party_dir"))
+ out = $$shadowed($$absolute_path(ninja/ninja, $$src_3rd_party_dir))
win32: out = $${out}.exe
- out = $$system_path($$out)
# If we did not find ninja, then we bootstrap it.
!exists($$out) {
- # If we are making a shadow build, copy the ninja sources to the build directory.
- !equals(PWD, $${OUT_PWD}) {
- log("Build directory is different from source directory - copying ninja sources to the build tree...")
- shadow_3rd_party_path = $$system_path($$shadowed($$src_3rd_party_dir))
-
- !exists($$dirname(out)): mkpath($$dirname(out))
- copy_dir_files {
- system("$$QMAKE_COPY_DIR $$system_quote($$system_path($$absolute_path("ninja", "$$src_3rd_party_dir"))) $$system_quote($$dirname(out))")
- } else {
- system("$$QMAKE_COPY_DIR $$system_quote($$system_path($$absolute_path("ninja", "$$src_3rd_party_dir"))) $$system_quote($$shadow_3rd_party_path)")
- }
- }
- system("cd $$system_quote($$dirname(out)) && python configure.py --bootstrap")
+ mkpath($$dirname(out))
+ ninja_configure = $$absolute_path(ninja/configure.py, $$src_3rd_party_dir)
+ system("cd $$system_quote($$system_path($$dirname(out))) && python $$system_quote($$system_path($$ninja_configure)) --bootstrap")
}
}
- return($$out)
+ return($$system_path($$out))
}
defineTest(skipBuild) {
diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py
index 053746f79..316805b6d 100755
--- a/tools/scripts/take_snapshot.py
+++ b/tools/scripts/take_snapshot.py
@@ -44,8 +44,6 @@ os.chdir(qtwebengine_root)
def isInGitBlacklist(file_path):
# We do need all the gyp files.
- if file_path.endswith('.gyp') or file_path.endswith('.gypi') or file_path.endswith('.isolate'):
- False
if ( '.gitignore' in file_path
or '.gitmodules' in file_path
or '.gitattributes' in file_path
@@ -59,6 +57,10 @@ def isInChromiumBlacklist(file_path):
# We do need all the gyp files.
if file_path.endswith('.gyp') or file_path.endswith('.gypi') or file_path.endswith('.isolate'):
return False
+ # We do need all the gn file.
+ if file_path.endswith('.gn') or file_path.endswith('.gni') or file_path.endswith('typemap') or \
+ file_path.endswith('.mojom'):
+ return False
if ( '_jni' in file_path
or 'jni_' in file_path
or 'testdata/' in file_path