summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--config.tests/winversion/winversion.cpp2
-rw-r--r--configure.json3
-rw-r--r--examples/webengine/quicknanobrowser/ApplicationRoot.qml3
-rw-r--r--examples/webengine/quicknanobrowser/BrowserWindow.qml6
-rw-r--r--examples/webengine/webengine.pro3
-rw-r--r--examples/webengine/webengineaction/doc/images/webengineaction-example.pngbin0 -> 100266 bytes
-rw-r--r--examples/webengine/webengineaction/doc/src/webengineaction.qdoc68
-rw-r--r--examples/webengine/webengineaction/main.cpp67
-rw-r--r--examples/webengine/webengineaction/main.qml166
-rw-r--r--examples/webengine/webengineaction/qml.qrc5
-rw-r--r--examples/webengine/webengineaction/webengineaction.pro10
-rw-r--r--examples/webenginewidgets/simplebrowser/main.cpp3
-rw-r--r--mkspecs/features/gn_generator.prf4
m---------src/3rdparty0
-rw-r--r--src/core/accessibility_activation_observer.cpp89
-rw-r--r--src/core/accessibility_activation_observer.h (renamed from src/core/net/qrc_protocol_handler_qt.cpp)32
-rw-r--r--src/core/api/core_api.pro1
-rw-r--r--src/core/api/qwebengineclientcertificatestore.h81
-rw-r--r--src/core/api/qwebengineurlrequestinfo.cpp24
-rw-r--r--src/core/api/qwebengineurlrequestinfo.h5
-rw-r--r--src/core/api/qwebengineurlrequestjob.cpp9
-rw-r--r--src/core/api/qwebengineurlrequestjob.h1
-rw-r--r--src/core/api/qwebengineurlschemehandler.cpp1
-rw-r--r--src/core/api/qwebengineurlschemehandler.h5
-rw-r--r--src/core/authentication_dialog_controller.cpp9
-rw-r--r--src/core/browser_accessibility_qt.cpp7
-rw-r--r--src/core/browser_accessibility_qt.h1
-rw-r--r--src/core/browser_main_parts_qt.cpp61
-rw-r--r--src/core/chromium_overrides.cpp9
-rw-r--r--src/core/client_cert_override_key.cpp137
-rw-r--r--src/core/client_cert_override_key_p.h52
-rw-r--r--src/core/client_cert_override_p.h63
-rw-r--r--src/core/client_cert_select_controller.cpp40
-rw-r--r--src/core/client_cert_select_controller.h2
-rw-r--r--src/core/color_chooser_controller.cpp3
-rw-r--r--src/core/color_chooser_controller.h3
-rw-r--r--src/core/compositor/chromium_gpu_helper.cpp (renamed from src/core/chromium_gpu_helper.cpp)17
-rw-r--r--src/core/compositor/chromium_gpu_helper.h (renamed from src/core/chromium_gpu_helper.h)9
-rw-r--r--src/core/compositor/compositor.cpp (renamed from src/core/compositor.cpp)82
-rw-r--r--src/core/compositor/compositor.h (renamed from src/core/compositor.h)38
-rw-r--r--src/core/compositor/compositor_resource.h122
-rw-r--r--src/core/compositor/compositor_resource_fence.cpp158
-rw-r--r--src/core/compositor/compositor_resource_fence.h (renamed from src/core/net/url_request_qrc_job_qt.h)47
-rw-r--r--src/core/compositor/compositor_resource_tracker.cpp259
-rw-r--r--src/core/compositor/compositor_resource_tracker.h126
-rw-r--r--src/core/compositor/content_gpu_client_qt.cpp59
-rw-r--r--src/core/compositor/content_gpu_client_qt.h57
-rw-r--r--src/core/compositor/delegated_frame_node.cpp (renamed from src/core/delegated_frame_node.cpp)559
-rw-r--r--src/core/compositor/delegated_frame_node.h (renamed from src/core/delegated_frame_node.h)70
-rw-r--r--src/core/compositor/stream_video_node.cpp (renamed from src/core/stream_video_node.cpp)0
-rw-r--r--src/core/compositor/stream_video_node.h (renamed from src/core/stream_video_node.h)0
-rw-r--r--src/core/compositor/yuv_video_node.cpp (renamed from src/core/yuv_video_node.cpp)0
-rw-r--r--src/core/compositor/yuv_video_node.h (renamed from src/core/yuv_video_node.h)0
-rw-r--r--src/core/config/common.pri9
-rw-r--r--src/core/config/mac_osx.pri2
-rw-r--r--src/core/configure.json32
-rw-r--r--src/core/content_browser_client_qt.cpp76
-rw-r--r--src/core/content_browser_client_qt.h5
-rw-r--r--src/core/content_client_qt.cpp6
-rw-r--r--src/core/content_client_qt.h3
-rw-r--r--src/core/content_main_delegate_qt.cpp21
-rw-r--r--src/core/content_main_delegate_qt.h3
-rw-r--r--src/core/core_chromium.pri48
-rw-r--r--src/core/devtools_frontend_qt.cpp18
-rw-r--r--src/core/download_manager_delegate_qt.cpp2
-rw-r--r--src/core/file_picker_controller.cpp37
-rw-r--r--src/core/file_picker_controller.h12
-rw-r--r--src/core/locked_ptr.h301
-rw-r--r--src/core/login_delegate_qt.cpp20
-rw-r--r--src/core/login_delegate_qt.h5
-rw-r--r--src/core/media_capture_devices_dispatcher.cpp46
-rw-r--r--src/core/media_capture_devices_dispatcher.h6
-rw-r--r--src/core/net/cookie_monster_delegate_qt.cpp47
-rw-r--r--src/core/net/network_delegate_qt.cpp147
-rw-r--r--src/core/net/network_delegate_qt.h4
-rw-r--r--src/core/net/proxy_config_service_qt.h2
-rw-r--r--src/core/net/qrc_url_scheme_handler.cpp68
-rw-r--r--src/core/net/qrc_url_scheme_handler.h55
-rw-r--r--src/core/net/url_request_context_getter_qt.cpp6
-rw-r--r--src/core/net/url_request_custom_job.cpp34
-rw-r--r--src/core/net/url_request_custom_job_delegate.cpp42
-rw-r--r--src/core/net/url_request_custom_job_delegate.h6
-rw-r--r--src/core/net/url_request_custom_job_proxy.cpp12
-rw-r--r--src/core/net/url_request_custom_job_proxy.h2
-rw-r--r--src/core/net/url_request_qrc_job_qt.cpp133
-rw-r--r--src/core/net/webui_controller_factory_qt.cpp3
-rw-r--r--src/core/ozone/gl_context_qt.cpp6
-rw-r--r--src/core/ozone/gl_surface_egl_qt.cpp18
-rw-r--r--src/core/ozone/gl_surface_qt.cpp4
-rw-r--r--src/core/ozone/gl_surface_wgl_qt.cpp4
-rw-r--r--src/core/ozone/ozone_platform_qt.cpp1
-rw-r--r--src/core/ozone/platform_window_qt.h3
-rw-r--r--src/core/permission_manager_qt.cpp5
-rw-r--r--src/core/permission_manager_qt.h2
-rw-r--r--src/core/printing/print_view_manager_base_qt.cpp25
-rw-r--r--src/core/printing/print_view_manager_qt.cpp84
-rw-r--r--src/core/printing/print_view_manager_qt.h4
-rw-r--r--src/core/process_main.cpp12
-rw-r--r--src/core/profile_adapter.cpp117
-rw-r--r--src/core/profile_adapter.h30
-rw-r--r--src/core/profile_adapter_client.h1
-rw-r--r--src/core/profile_io_data_qt.cpp115
-rw-r--r--src/core/profile_io_data_qt.h5
-rw-r--r--src/core/profile_qt.cpp11
-rw-r--r--src/core/profile_qt.h1
-rw-r--r--src/core/qtwebengine.gni11
-rw-r--r--src/core/qtwebengine_sources.gni13
-rw-r--r--src/core/quota_permission_context_qt.cpp18
-rw-r--r--src/core/qwebengineclientcertificatestore.cpp288
-rw-r--r--src/core/render_widget_host_view_qt.cpp181
-rw-r--r--src/core/render_widget_host_view_qt.h38
-rw-r--r--src/core/renderer/content_renderer_client_qt.cpp4
-rw-r--r--src/core/renderer/content_settings_observer_qt.cpp4
-rw-r--r--src/core/renderer/content_settings_observer_qt.h4
-rw-r--r--src/core/renderer/user_resource_controller.cpp8
-rw-r--r--src/core/renderer/web_channel_ipc_transport.cpp10
-rw-r--r--src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp4
-rw-r--r--src/core/resource_bundle_qt.cpp1
-rw-r--r--src/core/service/service_qt.cpp10
-rw-r--r--src/core/touch_handle_drawable_client.h (renamed from src/core/net/qrc_protocol_handler_qt.h)34
-rw-r--r--src/core/touch_handle_drawable_qt.cpp211
-rw-r--r--src/core/touch_handle_drawable_qt.h87
-rw-r--r--src/core/touch_selection_controller_client_qt.cpp343
-rw-r--r--src/core/touch_selection_controller_client_qt.h116
-rw-r--r--src/core/touch_selection_menu_controller.cpp91
-rw-r--r--src/core/touch_selection_menu_controller.h76
-rw-r--r--src/core/type_conversion.cpp15
-rw-r--r--src/core/type_conversion.h14
-rw-r--r--src/core/visited_links_manager_qt.cpp10
-rw-r--r--src/core/visited_links_manager_qt.h4
-rw-r--r--src/core/web_contents_adapter.cpp42
-rw-r--r--src/core/web_contents_adapter_client.h9
-rw-r--r--src/core/web_contents_delegate_qt.cpp20
-rw-r--r--src/core/web_contents_delegate_qt.h6
-rw-r--r--src/core/web_contents_view_qt.cpp13
-rw-r--r--src/core/web_contents_view_qt.h20
-rw-r--r--src/core/web_engine_context.cpp101
-rw-r--r--src/core/web_engine_context.h20
-rw-r--r--src/core/web_engine_context_threads.cpp135
-rw-r--r--src/core/web_engine_library_info.cpp1
-rw-r--r--src/core/web_event_factory.cpp2
-rw-r--r--src/plugins/plugins.pro2
-rw-r--r--src/src.pro22
-rw-r--r--src/webengine/api/qquickwebengineclientcertificateselection.cpp239
-rw-r--r--src/webengine/api/qquickwebengineclientcertificateselection_p.h135
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp154
-rw-r--r--src/webengine/api/qquickwebengineprofile.h17
-rw-r--r--src/webengine/api/qquickwebengineprofile_p.h2
-rw-r--r--src/webengine/api/qquickwebenginetouchhandleprovider.cpp80
-rw-r--r--src/webengine/api/qquickwebenginetouchhandleprovider_p_p.h77
-rw-r--r--src/webengine/api/qquickwebengineview.cpp91
-rw-r--r--src/webengine/api/qquickwebengineview_p.h7
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h22
-rw-r--r--src/webengine/api/qtwebengineglobal.h1
-rw-r--r--src/webengine/api/qtwebengineglobal_p.h4
-rw-r--r--src/webengine/configure.json29
-rw-r--r--src/webengine/doc/src/webengineview_lgpl.qdoc16
-rw-r--r--src/webengine/module.pro94
-rw-r--r--src/webengine/plugin/plugin.cpp41
-rw-r--r--src/webengine/plugin/plugin.pro6
-rw-r--r--src/webengine/plugin/plugins.qmltypes16
-rw-r--r--src/webengine/testsupport/plugin.cpp (renamed from src/webengine/plugin/testsupport/plugin.cpp)2
-rw-r--r--src/webengine/testsupport/qmldir (renamed from src/webengine/plugin/testsupport/qmldir)0
-rw-r--r--src/webengine/testsupport/testsupport.pro (renamed from src/webengine/plugin/testsupport/testsupport.pro)4
-rw-r--r--src/webengine/ui/TouchHandle.qml42
-rw-r--r--src/webengine/ui/TouchSelectionMenu.qml175
-rw-r--r--src/webengine/ui/ui.pro4
-rw-r--r--src/webengine/ui_delegates_manager.cpp79
-rw-r--r--src/webengine/ui_delegates_manager.h7
-rw-r--r--src/webengine/webengine.pro92
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp154
-rw-r--r--src/webenginewidgets/api/qwebenginepage.h3
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h9
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp109
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.h10
-rw-r--r--src/webenginewidgets/printer_worker.cpp147
-rw-r--r--src/webenginewidgets/printer_worker.h88
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp38
-rw-r--r--src/webenginewidgets/webenginewidgets.pro3
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp36
-rw-r--r--tests/auto/quick/dialogs/dialogs.pro2
-rw-r--r--tests/auto/quick/dialogs/tst_dialogs.cpp1
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp5
-rw-r--r--tests/auto/quick/qmltests/data/tst_download.qml20
-rw-r--r--tests/auto/quick/qmltests/data/tst_findText.qml4
-rw-r--r--tests/auto/quick/qmltests/data/tst_profile.qml66
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro1
-rw-r--r--tests/auto/quick/qquickwebengineview/BLACKLIST5
-rw-r--r--tests/auto/quick/qquickwebengineview/qquickwebengineview.pro2
-rw-r--r--tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp10
-rw-r--r--tests/auto/quick/quick.pro4
-rw-r--r--tests/auto/quick/tests.pri4
-rw-r--r--tests/auto/widgets/origins/tst_origins.cpp25
-rw-r--r--tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp269
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp1349
-rw-r--r--tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp61
-rw-r--r--tests/auto/widgets/qwebengineview/BLACKLIST3
-rw-r--r--tests/auto/widgets/qwebengineview/resources/image2.pngbin0 -> 14743 bytes
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp11
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.qrc1
-rw-r--r--tests/manual/widgets/inputmethods/testview.cpp11
-rw-r--r--tests/manual/widgets/webgl/main.cpp184
-rw-r--r--tests/manual/widgets/webgl/webgl.pro6
-rw-r--r--tests/manual/widgets/widgets.pro3
-rw-r--r--tools/scripts/gn_find_mocables.py3
-rwxr-xr-xtools/scripts/take_snapshot.py236
-rw-r--r--tools/scripts/version_resolver.py5
208 files changed, 7356 insertions, 3197 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 3c71512ec..26852b80b 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -5,4 +5,4 @@ QTWEBENGINE_OUT_ROOT = $$shadowed($$PWD)
load(qt_build_config)
CONFIG += warning_clean
-MODULE_VERSION = 5.12.2
+MODULE_VERSION = 5.13.0
diff --git a/config.tests/winversion/winversion.cpp b/config.tests/winversion/winversion.cpp
index 4d117b945..e9a4cff59 100644
--- a/config.tests/winversion/winversion.cpp
+++ b/config.tests/winversion/winversion.cpp
@@ -26,7 +26,7 @@
**
****************************************************************************/
-#if !defined(__clang__) && _MSC_FULL_VER < 191125507
+#if !defined(__clang__) && _MSC_FULL_VER < 191426428
#error unsupported Visual Studio version
#endif
diff --git a/configure.json b/configure.json
index 40d6bfe56..60b7342f7 100644
--- a/configure.json
+++ b/configure.json
@@ -1,5 +1,6 @@
{
"subconfigs": [
- "src/core"
+ "src/core",
+ "src/webengine"
]
}
diff --git a/examples/webengine/quicknanobrowser/ApplicationRoot.qml b/examples/webengine/quicknanobrowser/ApplicationRoot.qml
index 67b686541..3bc571546 100644
--- a/examples/webengine/quicknanobrowser/ApplicationRoot.qml
+++ b/examples/webengine/quicknanobrowser/ApplicationRoot.qml
@@ -49,7 +49,7 @@
****************************************************************************/
import QtQuick 2.1
-import QtWebEngine 1.2
+import QtWebEngine 1.9
QtObject {
id: root
@@ -57,6 +57,7 @@ QtObject {
property QtObject defaultProfile: WebEngineProfile {
storageName: "Profile"
offTheRecord: false
+ useForGlobalCertificateVerification: true
}
property QtObject otrProfile: WebEngineProfile {
diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
index 8d62482da..c0cb4283f 100644
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml
@@ -57,7 +57,7 @@ import QtQuick.Controls.Styles 1.0
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.0
import QtQuick.Window 2.1
-import QtWebEngine 1.7
+import QtWebEngine 1.9
ApplicationWindow {
id: browserWindow
@@ -490,6 +490,10 @@ ApplicationWindow {
tabs.removeTab(tabs.currentIndex);
}
+ onSelectClientCertificate: function(selection) {
+ selection.certificates[0].select();
+ }
+
Timer {
id: reloadTimer
interval: 0
diff --git a/examples/webengine/webengine.pro b/examples/webengine/webengine.pro
index b20b8f118..5ad620390 100644
--- a/examples/webengine/webengine.pro
+++ b/examples/webengine/webengine.pro
@@ -3,7 +3,8 @@ TEMPLATE=subdirs
SUBDIRS += \
customdialogs \
minimal \
- quicknanobrowser
+ quicknanobrowser \
+ webengineaction
qtHaveModule(quickcontrols2) {
SUBDIRS += \
diff --git a/examples/webengine/webengineaction/doc/images/webengineaction-example.png b/examples/webengine/webengineaction/doc/images/webengineaction-example.png
new file mode 100644
index 000000000..2e34bbf63
--- /dev/null
+++ b/examples/webengine/webengineaction/doc/images/webengineaction-example.png
Binary files differ
diff --git a/examples/webengine/webengineaction/doc/src/webengineaction.qdoc b/examples/webengine/webengineaction/doc/src/webengineaction.qdoc
new file mode 100644
index 000000000..672f86f0f
--- /dev/null
+++ b/examples/webengine/webengineaction/doc/src/webengineaction.qdoc
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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$
+**
+****************************************************************************/
+
+/*!
+ \example webengine/webengineaction
+ \title WebEngine Action Example
+ \ingroup webengine-examples
+ \brief A simple browser implemented using WebEngineActions.
+
+ \image webengineaction-example.png
+
+ \e {WebEngine Action Example} demonstrates how to perform actions on a web page
+ using the \l{WebEngineAction} type. It shows the minimum amount of code needed
+ to bind browser functionalities to input elements and build up a custom context
+ menu.
+
+ \include examples-run.qdocinc
+
+ \section1 Working With Web Engine Actions
+
+ An intended use of \l{WebEngineAction} is building a connection between UI
+ elements and browser commands. It can be added to menus and toolbars via
+ assigning its properties to the corresponding ones of the element.
+
+ The \l{ToolButton} relies on the properties provided by a
+ \l{WebEngineAction}. Clicking the button triggers backwards navigation on the
+ originating \l{WebEngineView} of the action.
+
+ \quotefromfile webengine/webengineaction/main.qml
+ \skipto ToolButton {
+ \printuntil }
+
+ The simplest way to create custom context menus is enumerating the required
+ \l{WebEngineAction} types in a data model and instantiating \l{MenuItem} types
+ for them, for example using a \l{Repeater}.
+
+ \quotefromfile webengine/webengineaction/main.qml
+ \skipto property Menu contextMenu: Menu {
+ \printuntil /^ {8}\}/
+
+ Assigning a \l{WebEngineAction} to multiple UI elements will keep them in sync.
+ As it can be seen in the picture above, if the browser engine disables a
+ navigation action, both corresponding menu items will be disabled.
+*/
diff --git a/examples/webengine/webengineaction/main.cpp b/examples/webengine/webengineaction/main.cpp
new file mode 100644
index 000000000..ce723a99b
--- /dev/null
+++ b/examples/webengine/webengineaction/main.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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 <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <qtwebengineglobal.h>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setOrganizationName("QtExamples");
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+
+ QtWebEngine::initialize();
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ return app.exec();
+}
diff --git a/examples/webengine/webengineaction/main.qml b/examples/webengine/webengineaction/main.qml
new file mode 100644
index 000000000..a3933ee41
--- /dev/null
+++ b/examples/webengine/webengineaction/main.qml
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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.0
+import QtQuick.Window 2.0
+import QtWebEngine 1.7
+import QtQuick.Controls 2.4
+import QtQuick.Layouts 1.11
+
+ApplicationWindow {
+ id: window
+ visible: true
+ width: 800
+ height: 600
+ title: qsTr("WebEngineAction Example")
+
+ header: ToolBar {
+ RowLayout {
+ anchors.fill: parent
+
+ ToolButton {
+ property int itemAction: WebEngineView.Back
+ text: webEngineView.action(itemAction).text
+ enabled: webEngineView.action(itemAction).enabled
+ onClicked: webEngineView.action(itemAction).trigger()
+ icon.name: webEngineView.action(itemAction).iconName
+ display: AbstractButton.TextUnderIcon
+ }
+
+ ToolButton {
+ property int itemAction: WebEngineView.Forward
+ text: webEngineView.action(itemAction).text
+ enabled: webEngineView.action(itemAction).enabled
+ onClicked: webEngineView.action(itemAction).trigger()
+ icon.name: webEngineView.action(itemAction).iconName
+ display: AbstractButton.TextUnderIcon
+ }
+
+ ToolButton {
+ property int itemAction: webEngineView.loading ? WebEngineView.Stop : WebEngineView.Reload
+ text: webEngineView.action(itemAction).text
+ enabled: webEngineView.action(itemAction).enabled
+ onClicked: webEngineView.action(itemAction).trigger()
+ icon.name: webEngineView.action(itemAction).iconName
+ display: AbstractButton.TextUnderIcon
+ }
+
+ TextField {
+ Layout.fillWidth: true
+
+ text: webEngineView.url
+ selectByMouse: true
+ onEditingFinished: webEngineView.url = text
+ }
+
+ ToolButton {
+ id: settingsButton
+ text: "Settings"
+ icon.name: "settings-configure"
+ display: AbstractButton.TextUnderIcon
+ onClicked: settingsMenu.open()
+ checked: settingsMenu.visible
+
+ Menu {
+ id: settingsMenu
+ y: settingsButton.height
+
+ MenuItem {
+ id: customContextMenuOption
+ checkable: true
+ checked: true
+
+ text: "Custom context menu"
+ }
+ }
+ }
+ }
+ }
+
+ WebEngineView {
+ id: webEngineView
+ url: "https://qt.io"
+ anchors.fill: parent
+
+ Component.onCompleted: {
+ profile.downloadRequested.connect(function(download){
+ download.accept();
+ })
+ }
+
+ property Menu contextMenu: Menu {
+ Repeater {
+ model: [
+ WebEngineView.Back,
+ WebEngineView.Forward,
+ WebEngineView.Reload,
+ WebEngineView.SavePage,
+ WebEngineView.Copy,
+ WebEngineView.Paste,
+ WebEngineView.Cut
+ ]
+ MenuItem {
+ text: webEngineView.action(modelData).text
+ enabled: webEngineView.action(modelData).enabled
+ onClicked: webEngineView.action(modelData).trigger()
+ icon.name: webEngineView.action(modelData).iconName
+ display: MenuItem.TextBesideIcon
+ }
+ }
+ }
+
+ onContextMenuRequested: function(request) {
+ if (customContextMenuOption.checked) {
+ request.accepted = true;
+ contextMenu.popup();
+ }
+ }
+ }
+}
diff --git a/examples/webengine/webengineaction/qml.qrc b/examples/webengine/webengineaction/qml.qrc
new file mode 100644
index 000000000..5f6483ac3
--- /dev/null
+++ b/examples/webengine/webengineaction/qml.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/webengine/webengineaction/webengineaction.pro b/examples/webengine/webengineaction/webengineaction.pro
new file mode 100644
index 000000000..13cc4602d
--- /dev/null
+++ b/examples/webengine/webengineaction/webengineaction.pro
@@ -0,0 +1,10 @@
+TEMPLATE = app
+
+QT += webengine
+
+SOURCES += main.cpp
+
+RESOURCES += qml.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/webengine/webengineaction
+INSTALLS += target
diff --git a/examples/webenginewidgets/simplebrowser/main.cpp b/examples/webenginewidgets/simplebrowser/main.cpp
index 0e8f86c8f..7b77a4bd2 100644
--- a/examples/webenginewidgets/simplebrowser/main.cpp
+++ b/examples/webenginewidgets/simplebrowser/main.cpp
@@ -52,6 +52,7 @@
#include "browserwindow.h"
#include "tabwidget.h"
#include <QApplication>
+#include <QWebEngineProfile>
#include <QWebEngineSettings>
QUrl commandLineUrlArgument()
@@ -74,6 +75,8 @@ int main(int argc, char **argv)
app.setWindowIcon(QIcon(QStringLiteral(":AppLogoColor.png")));
QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
+ QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true);
+ QWebEngineProfile::defaultProfile()->setUseForGlobalCertificateVerification();
QUrl url = commandLineUrlArgument();
diff --git a/mkspecs/features/gn_generator.prf b/mkspecs/features/gn_generator.prf
index c1399a453..e6ae263ac 100644
--- a/mkspecs/features/gn_generator.prf
+++ b/mkspecs/features/gn_generator.prf
@@ -29,12 +29,12 @@ isEmpty(GN_FIND_MOCABLES_SCRIPT): GN_FIND_MOCABLES_SCRIPT = "//build/gn_find_moc
# MOC SETUP
GN_CONTENTS += "moc_source_h_files = exec_script(\"$$GN_FIND_MOCABLES_SCRIPT\","
-GN_CONTENTS += " [ \"$$_PRO_FILE_PWD_\","
+GN_CONTENTS += " ["
for (headerfile, HEADERS): GN_CONTENTS += " \"$$GN_SRC_DIR/$$headerfile\","
GN_CONTENTS += " ], \"list lines\", [\"$$system_path($$_PRO_FILE_)\"]"\
")"
GN_CONTENTS += "moc_source_cpp_files = exec_script(\"$$GN_FIND_MOCABLES_SCRIPT\","
-GN_CONTENTS += " [ \"$$_PRO_FILE_PWD_\","
+GN_CONTENTS += " ["
for (sourcefile, SOURCES): GN_CONTENTS += " \"$$GN_SRC_DIR/$$sourcefile\","
GN_CONTENTS += " ], \"list lines\", [\"$$system_path($$_PRO_FILE_)\"]"\
")"
diff --git a/src/3rdparty b/src/3rdparty
-Subproject 323b45aa242e0b4e75689d67418ec124ba1ca81
+Subproject c677809fe785df63fe97608cb5a949302b2f0c6
diff --git a/src/core/accessibility_activation_observer.cpp b/src/core/accessibility_activation_observer.cpp
new file mode 100644
index 000000000..75ad90c54
--- /dev/null
+++ b/src/core/accessibility_activation_observer.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "accessibility_activation_observer.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+
+namespace QtWebEngineCore {
+
+namespace {
+
+bool isAccessibilityEnabled() {
+ // On Linux accessibility is disabled by default due to performance issues,
+ // and can be re-enabled by setting the QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment
+ // variable. For details, see QTBUG-59922.
+#ifdef Q_OS_LINUX
+ static bool accessibility_enabled
+ = qEnvironmentVariableIsSet("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY");
+#else
+ const bool accessibility_enabled = true;
+#endif
+ return accessibility_enabled;
+}
+
+} // namespace
+
+AccessibilityActivationObserver::AccessibilityActivationObserver()
+{
+ if (isAccessibilityEnabled()) {
+ QAccessible::installActivationObserver(this);
+ if (QAccessible::isActive())
+ content::BrowserAccessibilityStateImpl::GetInstance()->EnableAccessibility();
+ }
+}
+
+AccessibilityActivationObserver::~AccessibilityActivationObserver()
+{
+ QAccessible::removeActivationObserver(this);
+}
+
+void AccessibilityActivationObserver::accessibilityActiveChanged(bool active)
+{
+ if (active)
+ content::BrowserAccessibilityStateImpl::GetInstance()->EnableAccessibility();
+ else
+ content::BrowserAccessibilityStateImpl::GetInstance()->DisableAccessibility();
+}
+
+} // namespace QtWebEngineCore
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/core/net/qrc_protocol_handler_qt.cpp b/src/core/accessibility_activation_observer.h
index eb716f182..e42c83eb5 100644
--- a/src/core/net/qrc_protocol_handler_qt.cpp
+++ b/src/core/accessibility_activation_observer.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -37,27 +37,27 @@
**
****************************************************************************/
-#include "qrc_protocol_handler_qt.h"
-#include "url_request_qrc_job_qt.h"
+#ifndef ACCESSIBILITY_ACTIVATION_OBSERVER_H
+#define ACCESSIBILITY_ACTIVATION_OBSERVER_H
-#include "net/base/net_errors.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_error_job.h"
+#ifndef QT_NO_ACCESSIBILITY
+#include <QtGui/qaccessible.h>
namespace QtWebEngineCore {
-const char kQrcSchemeQt[] = "qrc";
+class RenderWidgetHostViewQt;
-QrcProtocolHandlerQt::QrcProtocolHandlerQt()
+class AccessibilityActivationObserver : public QAccessible::ActivationObserver
{
-}
+public:
+ AccessibilityActivationObserver();
+ ~AccessibilityActivationObserver();
-net::URLRequestJob *QrcProtocolHandlerQt::MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const
-{
- if (!networkDelegate)
- return new net::URLRequestErrorJob(request, Q_NULLPTR, net::ERR_ACCESS_DENIED);
-
- return new URLRequestQrcJobQt(request, networkDelegate);
-}
+ void accessibilityActiveChanged(bool active) override;
+};
} // namespace QtWebEngineCore
+
+#endif // QT_NO_ACCESSIBILITY
+
+#endif // ACCESSIBILITY_ACTIVATION_OBSERVER_H
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 38dc6b39d..b5bb93847 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -32,6 +32,7 @@ gcc: QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter
HEADERS = \
qwebenginecallback.h \
qwebenginecallback_p.h \
+ qwebengineclientcertificatestore.h \
qtwebenginecoreglobal.h \
qtwebenginecoreglobal_p.h \
qwebenginecookiestore.h \
diff --git a/src/core/api/qwebengineclientcertificatestore.h b/src/core/api/qwebengineclientcertificatestore.h
new file mode 100644
index 000000000..6ba998465
--- /dev/null
+++ b/src/core/api/qwebengineclientcertificatestore.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBENGINECLIENTCERTIFICATESTORE_H
+#define QWEBENGINECLIENTCERTIFICATESTORE_H
+
+#include <QtWebEngineCore/qtwebenginecoreglobal.h>
+
+#include <QtNetwork/qsslcertificate.h>
+#include <QtNetwork/qsslkey.h>
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(ssl)
+
+struct QWebEngineClientCertificateStoreData;
+
+class QWEBENGINECORE_EXPORT QWebEngineClientCertificateStore {
+
+public:
+ struct Entry {
+ QSslKey privateKey;
+ QSslCertificate certificate;
+ };
+
+ static QWebEngineClientCertificateStore *getInstance();
+ void add(const QSslCertificate &certificate, const QSslKey &privateKey);
+ QList<Entry> toList() const;
+ void remove(Entry entry);
+ void clear();
+
+private:
+ static QWebEngineClientCertificateStore *m_instance;
+ Q_DISABLE_COPY(QWebEngineClientCertificateStore)
+
+ QWebEngineClientCertificateStore();
+ ~QWebEngineClientCertificateStore();
+ QWebEngineClientCertificateStoreData *d_ptr;
+};
+
+#endif // QT_CONFIG(ssl)
+
+QT_END_NAMESPACE
+
+#endif // QWebEngineClientCertificateStore_H
diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp
index ea9081fc1..c3e5b5445 100644
--- a/src/core/api/qwebengineurlrequestinfo.cpp
+++ b/src/core/api/qwebengineurlrequestinfo.cpp
@@ -115,8 +115,11 @@ ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::OtherNavigation, Q
\fn void QWebEngineUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
Reimplementing this virtual function makes it possible to intercept URL
- requests. This function is executed on the IO thread, and therefore running
- long tasks here will block networking.
+ requests. For interceptors installed on a QWebEngineProfile, the function is executed
+ on the I/O thread, and thus it may not be thread-safe to interact with pages. If the
+ interceptor was installed on a QWebEnginePage, the function is executed on the main
+ application thread, and can safely interact with other user classes. Both versions will
+ be stalling the URL request until handled.
\a info contains the information about the URL request and will track internally
whether its members have been altered.
@@ -140,10 +143,17 @@ QWebEngineUrlRequestInfoPrivate::QWebEngineUrlRequestInfoPrivate(QWebEngineUrlRe
/*!
\internal
*/
+QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfo &&p)
+ : d_ptr(p.d_ptr.take())
+{
+}
+
+/*!
+ \internal
+*/
QWebEngineUrlRequestInfo::~QWebEngineUrlRequestInfo()
{
-
}
/*!
@@ -260,6 +270,14 @@ bool QWebEngineUrlRequestInfo::changed() const
}
/*!
+ \internal
+*/
+void QWebEngineUrlRequestInfo::resetChanged()
+{
+ d_ptr->changed = false;
+}
+
+/*!
Redirects this request to \a url.
It is only possible to redirect requests that do not have payload data, such as GET requests.
*/
diff --git a/src/core/api/qwebengineurlrequestinfo.h b/src/core/api/qwebengineurlrequestinfo.h
index 68c46dcf4..e1f9ca6ef 100644
--- a/src/core/api/qwebengineurlrequestinfo.h
+++ b/src/core/api/qwebengineurlrequestinfo.h
@@ -47,6 +47,7 @@
namespace QtWebEngineCore {
class NetworkDelegateQt;
+class URLRequestNotification;
}
QT_BEGIN_NAMESPACE
@@ -104,10 +105,14 @@ public:
private:
friend class QtWebEngineCore::NetworkDelegateQt;
+ friend class QtWebEngineCore::URLRequestNotification;
Q_DISABLE_COPY(QWebEngineUrlRequestInfo)
Q_DECLARE_PRIVATE(QWebEngineUrlRequestInfo)
+ void resetChanged();
+
QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPrivate *p);
+ QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfo &&p);
~QWebEngineUrlRequestInfo();
QScopedPointer<QWebEngineUrlRequestInfoPrivate> d_ptr;
};
diff --git a/src/core/api/qwebengineurlrequestjob.cpp b/src/core/api/qwebengineurlrequestjob.cpp
index c3541598b..41b43d42c 100644
--- a/src/core/api/qwebengineurlrequestjob.cpp
+++ b/src/core/api/qwebengineurlrequestjob.cpp
@@ -140,6 +140,15 @@ QUrl QWebEngineUrlRequestJob::initiator() const
}
/*!
+ \since 5.13
+ Returns any HTTP headers added to the request.
+*/
+const QMap<QByteArray, QByteArray> &QWebEngineUrlRequestJob::requestHeaders() const
+{
+ return d_ptr->requestHeaders();
+}
+
+/*!
Replies to the request with \a device and the MIME type \a contentType.
The user has to be aware that \a device will be used on another thread
diff --git a/src/core/api/qwebengineurlrequestjob.h b/src/core/api/qwebengineurlrequestjob.h
index 7ce8be7ec..55ec7c6d2 100644
--- a/src/core/api/qwebengineurlrequestjob.h
+++ b/src/core/api/qwebengineurlrequestjob.h
@@ -73,6 +73,7 @@ public:
QUrl requestUrl() const;
QByteArray requestMethod() const;
QUrl initiator() const;
+ const QMap<QByteArray, QByteArray> &requestHeaders() const;
void reply(const QByteArray &contentType, QIODevice *device);
void fail(Error error);
diff --git a/src/core/api/qwebengineurlschemehandler.cpp b/src/core/api/qwebengineurlschemehandler.cpp
index 6f06b2c6e..2e93f4b73 100644
--- a/src/core/api/qwebengineurlschemehandler.cpp
+++ b/src/core/api/qwebengineurlschemehandler.cpp
@@ -111,7 +111,6 @@ QWebEngineUrlSchemeHandler::QWebEngineUrlSchemeHandler(QObject *parent)
*/
QWebEngineUrlSchemeHandler::~QWebEngineUrlSchemeHandler()
{
- Q_EMIT _q_destroyedUrlSchemeHandler(this);
}
/*!
diff --git a/src/core/api/qwebengineurlschemehandler.h b/src/core/api/qwebengineurlschemehandler.h
index 23fee4b95..549778561 100644
--- a/src/core/api/qwebengineurlschemehandler.h
+++ b/src/core/api/qwebengineurlschemehandler.h
@@ -60,11 +60,6 @@ public:
virtual void requestStarted(QWebEngineUrlRequestJob*) = 0;
-#ifndef Q_QDOC
-Q_SIGNALS:
- void _q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*);
-#endif
-
private:
Q_DISABLE_COPY(QWebEngineUrlSchemeHandler)
};
diff --git a/src/core/authentication_dialog_controller.cpp b/src/core/authentication_dialog_controller.cpp
index bd23d1768..1133b0bc1 100644
--- a/src/core/authentication_dialog_controller.cpp
+++ b/src/core/authentication_dialog_controller.cpp
@@ -40,7 +40,9 @@
#include "authentication_dialog_controller.h"
#include "authentication_dialog_controller_p.h"
+#include "base/task/post_task.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/browser_task_traits.h"
namespace QtWebEngineCore {
@@ -51,9 +53,10 @@ AuthenticationDialogControllerPrivate::AuthenticationDialogControllerPrivate(Log
void AuthenticationDialogControllerPrivate::dialogFinished(bool accepted, const QString &user, const QString &password)
{
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::Bind(&LoginDelegateQt::sendAuthToRequester, loginDelegate, accepted, user, password));
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&LoginDelegateQt::sendAuthToRequester,
+ loginDelegate, accepted, user, password));
}
AuthenticationDialogController::AuthenticationDialogController(AuthenticationDialogControllerPrivate *dd)
diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp
index a672ccc06..c906071f2 100644
--- a/src/core/browser_accessibility_qt.cpp
+++ b/src/core/browser_accessibility_qt.cpp
@@ -61,6 +61,11 @@ const BrowserAccessibilityQt *ToBrowserAccessibilityQt(const BrowserAccessibilit
return static_cast<const BrowserAccessibilityQt *>(obj);
}
+QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj)
+{
+ return static_cast<BrowserAccessibilityQt *>(obj);
+}
+
BrowserAccessibilityQt::BrowserAccessibilityQt()
{
QAccessible::registerAccessibleInterface(this);
@@ -356,6 +361,8 @@ QAccessible::Role BrowserAccessibilityQt::role() const
return QAccessible::EditableText;
case ax::mojom::Role::kInputTime:
return QAccessible::SpinBox;
+ case ax::mojom::Role::kKeyboard:
+ return QAccessible::NoRole; // FIXME
case ax::mojom::Role::kLabelText:
return QAccessible::StaticText;
case ax::mojom::Role::kLayoutTable:
diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h
index 345ee9862..decfc1e9d 100644
--- a/src/core/browser_accessibility_qt.h
+++ b/src/core/browser_accessibility_qt.h
@@ -146,6 +146,7 @@ public:
};
const BrowserAccessibilityQt *ToBrowserAccessibilityQt(const BrowserAccessibility *obj);
+QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *acc);
} // namespace content
diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp
index 8f39386d4..cfe9ea8bb 100644
--- a/src/core/browser_main_parts_qt.cpp
+++ b/src/core/browser_main_parts_qt.cpp
@@ -59,6 +59,12 @@
#include <QEventLoop>
#include <QObject>
#include <QTimerEvent>
+#include <QtGui/qtgui-config.h>
+
+#if QT_CONFIG(opengl)
+#include "ui/gl/gl_context.h"
+#include <QOpenGLContext>
+#endif
#if defined(OS_MACOSX)
#include "ui/base/idle/idle.h"
@@ -156,8 +162,55 @@ protected:
}
private:
+ // Both Qt and Chromium keep track of the current GL context by using
+ // thread-local variables, and naturally they are completely unaware of each
+ // other. As a result, when a QOpenGLContext is made current, the previous
+ // gl::GLContext is not released, and vice-versa. This is fine as long as
+ // each thread uses exclusively either Qt or Chromium GL bindings, which is
+ // usually the case.
+ //
+ // The only exception is when the GL driver is considered thread-unsafe
+ // (QOpenGLContext::supportsThreadedOpenGL() is false), in which case we
+ // have to run all GL operations, including Chromium's GPU service, on the
+ // UI thread. Now the bindings are being mixed and both Qt and Chromium get
+ // quite confused regarding the current state of the surface.
+ //
+ // To get this to work we have to release the current QOpenGLContext before
+ // executing any tasks from Chromium's GPU service and the gl::GLContext
+ // afterwards. Since GPU service just posts tasks to the UI thread task
+ // runner, we'll have to instrument the entire UI thread message pump.
+ class ScopedGLContextChecker
+ {
+#if QT_CONFIG(opengl)
+ public:
+ ScopedGLContextChecker()
+ {
+ if (!m_enabled)
+ return;
+
+ if (QOpenGLContext *context = QOpenGLContext::currentContext())
+ context->doneCurrent();
+ }
+
+ ~ScopedGLContextChecker()
+ {
+ if (!m_enabled)
+ return;
+
+ if (gl::GLContext *context = gl::GLContext::GetCurrent())
+ context->ReleaseCurrent(nullptr);
+ }
+
+ private:
+ bool m_enabled = !QOpenGLContext::supportsThreadedOpenGL();
+#endif // QT_CONFIG(opengl)
+ };
+
+
void handleScheduledWork()
{
+ ScopedGLContextChecker glContextChecker;
+
bool more_work_is_plausible = m_delegate->DoWork();
base::TimeTicks delayed_work_time;
@@ -230,11 +283,9 @@ void BrowserMainPartsQt::ServiceManagerConnectionStarted(content::ServiceManager
{
ServiceQt::GetInstance()->InitConnector();
connection->GetConnector()->StartService(service_manager::Identity("qtwebengine"));
- if (resource_coordinator::IsResourceCoordinatorEnabled()) {
- m_processResourceCoordinator = std::make_unique<resource_coordinator::ProcessResourceCoordinator>(connection->GetConnector());
- m_processResourceCoordinator->SetLaunchTime(base::Time::Now());
- m_processResourceCoordinator->SetPID(base::Process::Current().Pid());
- }
+ m_processResourceCoordinator = std::make_unique<resource_coordinator::ProcessResourceCoordinator>(connection->GetConnector());
+ m_processResourceCoordinator->SetLaunchTime(base::Time::Now());
+ m_processResourceCoordinator->SetPID(base::Process::Current().Pid());
}
} // namespace QtWebEngineCore
diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp
index 841dcf4c9..c25d6dda9 100644
--- a/src/core/chromium_overrides.cpp
+++ b/src/core/chromium_overrides.cpp
@@ -59,6 +59,7 @@
#include <QWindow>
#include <QFontDatabase>
#include <QStringList>
+#include <QLibraryInfo>
#if defined(USE_AURA) && !defined(USE_OZONE)
#include "ui/base/dragdrop/os_exchange_data.h"
@@ -119,6 +120,14 @@ void WebContentsView::GetDefaultScreenInfo(content::ScreenInfo* results)
QtWebEngineCore::GetScreenInfoFromNativeWindow(&dummy, results);
}
+#if defined(Q_OS_MACOS)
+std::string getQtPrefix()
+{
+ const QString prefix = QLibraryInfo::location(QLibraryInfo::PrefixPath);
+ return prefix.toStdString();
+}
+#endif
+
} // namespace content
#if defined(USE_AURA) || defined(USE_OZONE)
diff --git a/src/core/client_cert_override_key.cpp b/src/core/client_cert_override_key.cpp
new file mode 100644
index 000000000..99ddf7466
--- /dev/null
+++ b/src/core/client_cert_override_key.cpp
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLIENT_CERT_OVERRIDE_KEY_H
+#define CLIENT_CERT_OVERRIDE_KEY_H
+
+#include "client_cert_override_key_p.h"
+
+#include "third_party/boringssl/src/include/openssl/ssl.h"
+#include "third_party/boringssl/src/include/openssl/digest.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
+#include "third_party/boringssl/src/include/openssl/pem.h"
+
+#include <utility>
+#include <QByteArray>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "net/base/net_errors.h"
+#include "net/ssl/ssl_platform_key_util.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/threaded_ssl_private_key.h"
+
+namespace net {
+
+namespace {
+
+class SSLPlatformKeyOverride : public ThreadedSSLPrivateKey::Delegate {
+public:
+ SSLPlatformKeyOverride(const QByteArray &sslKeyInBytes)
+ {
+ mem_ = BIO_new_mem_buf(sslKeyInBytes, -1);
+ key_ = PEM_read_bio_PrivateKey(mem_, NULL, 0, NULL);
+ }
+
+ ~SSLPlatformKeyOverride() override {
+ if (key_)
+ EVP_PKEY_free(key_);
+ if (mem_)
+ BIO_free(mem_);
+ }
+
+ Error Sign(uint16_t algorithm,
+ base::span<const uint8_t> input,
+ std::vector<uint8_t>* signature) override {
+ bssl::ScopedEVP_MD_CTX ctx;
+ EVP_PKEY_CTX* pctx;
+ if (!EVP_DigestSignInit(ctx.get(), &pctx,
+ SSL_get_signature_algorithm_digest(algorithm),
+ nullptr, key_)) {
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+
+ if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
+ if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
+ !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* hash length */)) {
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ }
+ size_t sig_len = 0;
+ if (!EVP_DigestSign(ctx.get(), NULL, &sig_len, input.data(), input.size()))
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ signature->resize(sig_len);
+ if (!EVP_DigestSign(ctx.get(), signature->data(), &sig_len, input.data(),
+ input.size())) {
+ return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ }
+ signature->resize(sig_len);
+ return OK;
+ }
+
+ std::vector<uint16_t> GetAlgorithmPreferences() override {
+ return {
+ SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA512,
+ SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA256,
+ };
+ }
+
+private:
+ EVP_PKEY* key_;
+ BIO * mem_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyOverride);
+};
+
+} // namespace
+
+scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(const QByteArray &sslKeyInBytes) {
+ if (sslKeyInBytes.isEmpty())
+ return nullptr;
+
+ return base::MakeRefCounted<ThreadedSSLPrivateKey>(
+ std::make_unique<SSLPlatformKeyOverride>(sslKeyInBytes),
+ GetSSLPlatformKeyTaskRunner());
+}
+
+} // namespace net
+
+#endif
diff --git a/src/core/client_cert_override_key_p.h b/src/core/client_cert_override_key_p.h
new file mode 100644
index 000000000..7ac610be4
--- /dev/null
+++ b/src/core/client_cert_override_key_p.h
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLIENT_CERT_OVERRIDE_KEY_P_H
+#define CLIENT_CERT_OVERRIDE_KEY_P_H
+
+#include "net/ssl/ssl_private_key.h"
+
+#include <QByteArray>
+
+namespace net {
+ class SSLPrivateKey;
+ scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(const QByteArray &sslKeyInBytes);
+} // namespace net
+
+#endif
diff --git a/src/core/client_cert_override_p.h b/src/core/client_cert_override_p.h
new file mode 100644
index 000000000..b222bf810
--- /dev/null
+++ b/src/core/client_cert_override_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLIENT_CERT_OVERRIDE_P_H
+#define CLIENT_CERT_OVERRIDE_P_H
+
+#include "net/ssl/client_cert_store.h"
+#include "base/callback_forward.h"
+#include "net/cert/x509_certificate.h"
+
+namespace net {
+class SSLCertRequestInfo;
+class ClientCertOverrideStore : public ClientCertStore
+{
+public:
+ ClientCertOverrideStore();
+ virtual ~ClientCertOverrideStore() override;
+ void GetClientCerts(const SSLCertRequestInfo &cert_request_info,
+ const ClientCertListCallback &callback) override;
+private:
+ std::unique_ptr<net::ClientCertStore> getNativeStore();
+};
+} // namespace net
+
+#endif
+
+
diff --git a/src/core/client_cert_select_controller.cpp b/src/core/client_cert_select_controller.cpp
index 7d08d57c1..0baaf2bc5 100644
--- a/src/core/client_cert_select_controller.cpp
+++ b/src/core/client_cert_select_controller.cpp
@@ -48,6 +48,8 @@
#include "type_conversion.h"
+#include <QDebug>
+
QT_BEGIN_NAMESPACE
using namespace QtWebEngineCore;
@@ -76,17 +78,40 @@ ClientCertSelectController::~ClientCertSelectController()
void ClientCertSelectController::selectNone()
{
if (m_selected) {
- qWarning() << "ClientCertSelectController::selectNone() certicate already selected";
+ LOG(WARNING) << "ClientCertSelectController::selectNone() certificate already selected";
return;
}
m_selected = true;
m_delegate->ContinueWithCertificate(nullptr, nullptr);
}
+void ClientCertSelectController::select(int index)
+{
+ if (m_selected) {
+ LOG(WARNING) << "ClientCertSelectController::select() certificate already selected";
+ return;
+ }
+ for (auto &certInfo : m_clientCerts) {
+ if (index == 0) {
+ m_selected = true;
+ scoped_refptr<net::X509Certificate> cert = certInfo->certificate();
+ net::ClientCertIdentity::SelfOwningAcquirePrivateKey(
+ std::move(certInfo),
+ base::Bind(&content::ClientCertificateDelegate::ContinueWithCertificate,
+ base::Passed(std::move(m_delegate)), std::move(cert)));
+ return;
+ }
+ std::vector<std::string> pem_encoded;
+ if (certInfo->certificate()->GetPEMEncodedChain(&pem_encoded))
+ --index;
+ }
+ LOG(WARNING) << "ClientCertSelectController::select() index out of range:" << index;
+}
+
void ClientCertSelectController::select(const QSslCertificate &certificate)
{
if (m_selected) {
- qWarning() << "ClientCertSelectController::select() certicate already selected";
+ LOG(WARNING) << "ClientCertSelectController::select() certificate already selected";
return;
}
QByteArray derCertificate = certificate.toDer();
@@ -103,19 +128,20 @@ void ClientCertSelectController::select(const QSslCertificate &certificate)
return;
}
}
- qWarning() << "ClientCertSelectController::select() - selected client certificate not recognized."
- << " Selected certificate needs to be one of the offered";
+ LOG(WARNING) << "ClientCertSelectController::select() - selected client certificate not recognized."
+ << " Selected certificate needs to be one of the offered";
}
QVector<QSslCertificate> ClientCertSelectController::certificates() const
{
- QVector<QSslCertificate> out;
+ if (!m_certificates.isEmpty())
+ return m_certificates;
for (auto &cert : m_clientCerts) {
std::vector<std::string> pem_encoded;
if (cert->certificate()->GetPEMEncodedChain(&pem_encoded))
- out.append(QSslCertificate(QByteArray::fromStdString(pem_encoded.front())));
+ m_certificates.append(QSslCertificate(QByteArray::fromStdString(pem_encoded.front())));
}
- return out;
+ return m_certificates;
}
#endif // !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
diff --git a/src/core/client_cert_select_controller.h b/src/core/client_cert_select_controller.h
index 46324ee90..8f4f78d94 100644
--- a/src/core/client_cert_select_controller.h
+++ b/src/core/client_cert_select_controller.h
@@ -83,6 +83,7 @@ public:
#if !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
void selectNone();
void select(const QSslCertificate &certificate);
+ void select(int index);
QVector<QSslCertificate> certificates() const;
#endif
@@ -91,6 +92,7 @@ private:
QUrl m_hostAndPort;
std::vector<std::unique_ptr<net::ClientCertIdentity>> m_clientCerts;
std::unique_ptr<content::ClientCertificateDelegate> m_delegate;
+ mutable QVector<QSslCertificate> m_certificates;
bool m_selected;
};
diff --git a/src/core/color_chooser_controller.cpp b/src/core/color_chooser_controller.cpp
index 26d675908..361ff93ba 100644
--- a/src/core/color_chooser_controller.cpp
+++ b/src/core/color_chooser_controller.cpp
@@ -43,6 +43,9 @@
#include "color_chooser_controller_p.h"
#include "type_conversion.h"
+#include <QColor>
+#include <QVariant>
+
namespace QtWebEngineCore {
ColorChooserControllerPrivate::ColorChooserControllerPrivate(content::WebContents *content, const QColor &color)
diff --git a/src/core/color_chooser_controller.h b/src/core/color_chooser_controller.h
index 4c1b81a9a..e5daa09a8 100644
--- a/src/core/color_chooser_controller.h
+++ b/src/core/color_chooser_controller.h
@@ -55,6 +55,9 @@
#include <QObject>
+QT_FORWARD_DECLARE_CLASS(QColor)
+QT_FORWARD_DECLARE_CLASS(QVariant)
+
namespace QtWebEngineCore {
class ColorChooserControllerPrivate;
diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/compositor/chromium_gpu_helper.cpp
index 92a8b13ed..71d0f3687 100644
--- a/src/core/chromium_gpu_helper.cpp
+++ b/src/core/compositor/chromium_gpu_helper.cpp
@@ -43,10 +43,14 @@
#include "chromium_gpu_helper.h"
+// Some headers include the namespace ws, and can not coexist with
+// Qt headers that include QTextStream, which includes most QSG headers
+// via QMatrix4x4.
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+
// Including gpu/command_buffer headers before content/gpu headers makes sure that
// guards are defined to prevent duplicate definition errors with forward declared
// GL typedefs cascading through content header includes.
-#include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_base.h"
@@ -62,12 +66,6 @@ scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner()
return content::GpuChildThread::instance()->main_thread_runner();
}
-gpu::SyncPointManager *sync_point_manager()
-{
- gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->gpu_channel_manager();
- return gpuChannelManager->sync_point_manager();
-}
-
gpu::MailboxManager *mailbox_manager()
{
gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->gpu_channel_manager();
@@ -85,6 +83,11 @@ unsigned int service_id(gpu::TextureBase *tex)
return tex->service_id();
}
+void ProgressFlingIfNeeded(content::RenderWidgetHost *host, const base::TimeTicks &current_time)
+{
+ content::RenderWidgetHostImpl::From(host)->ProgressFlingIfNeeded(current_time);
+}
+
#ifdef Q_OS_QNX
EGLStreamData eglstream_connect_consumer(gpu::Texture *tex)
{
diff --git a/src/core/chromium_gpu_helper.h b/src/core/compositor/chromium_gpu_helper.h
index 21b764997..4086d12ab 100644
--- a/src/core/chromium_gpu_helper.h
+++ b/src/core/compositor/chromium_gpu_helper.h
@@ -46,11 +46,15 @@
namespace base {
class SingleThreadTaskRunner;
+class TimeTicks;
+}
+
+namespace content {
+class RenderWidgetHost;
}
namespace gpu {
struct Mailbox;
-class SyncPointManager;
class MailboxManager;
class TextureBase;
}
@@ -61,12 +65,13 @@ class TextureBase;
// functions should only be forward-declared and considered as opaque types.
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner();
-gpu::SyncPointManager *sync_point_manager();
gpu::MailboxManager *mailbox_manager();
gpu::TextureBase* ConsumeTexture(gpu::MailboxManager *mailboxManager, unsigned target, const gpu::Mailbox& mailbox);
unsigned int service_id(gpu::TextureBase *tex);
+void ProgressFlingIfNeeded(content::RenderWidgetHost *host, const base::TimeTicks &current_time);
+
#ifdef Q_OS_QNX
typedef void* EGLDisplay;
typedef void* EGLStreamKHR;
diff --git a/src/core/compositor.cpp b/src/core/compositor/compositor.cpp
index f7a5e651c..0660c155b 100644
--- a/src/core/compositor.cpp
+++ b/src/core/compositor/compositor.cpp
@@ -39,26 +39,27 @@
#include "compositor.h"
+#include "compositor_resource_tracker.h"
#include "delegated_frame_node.h"
-#include "render_widget_host_view_qt.h"
+#include "base/task/post_task.h"
#include "components/viz/common/resources/returned_resource.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
namespace QtWebEngineCore {
-Compositor::Compositor(RenderWidgetHostViewQt *hostView)
- : m_chromiumCompositorData(new ChromiumCompositorData)
- , m_view(hostView)
+Compositor::Compositor(content::RenderWidgetHost *host)
+ : m_resourceTracker(new CompositorResourceTracker)
+ , m_host(host)
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- base::SingleThreadTaskRunner *taskRunner =
- content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI).get();
+ m_taskRunner = base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI});
m_beginFrameSource =
std::make_unique<viz::DelayBasedBeginFrameSource>(
- std::make_unique<viz::DelayBasedTimeSource>(taskRunner),
+ std::make_unique<viz::DelayBasedTimeSource>(m_taskRunner.get()),
viz::BeginFrameSource::kNotRestartableId);
}
@@ -67,13 +68,6 @@ Compositor::~Compositor()
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
-void Compositor::setViewDelegate(RenderWidgetHostViewQtDelegate *viewDelegate)
-{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- m_viewDelegate = viewDelegate;
-}
-
void Compositor::setFrameSinkClient(viz::mojom::CompositorFrameSinkClient *frameSinkClient)
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -85,7 +79,7 @@ void Compositor::setFrameSinkClient(viz::mojom::CompositorFrameSinkClient *frame
// should not be returned.
//
// TODO(juvaldma): Can there be a pending frame from the old client?
- m_resourcesToRelease.clear();
+ m_resourceTracker->returnResources();
m_frameSinkClient = frameSinkClient;
}
@@ -104,21 +98,19 @@ void Compositor::setNeedsBeginFrames(bool needsBeginFrames)
m_needsBeginFrames = needsBeginFrames;
}
-void Compositor::submitFrame(viz::CompositorFrame frame)
+void Compositor::submitFrame(viz::CompositorFrame frame, base::OnceClosure callback)
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- DCHECK(!m_havePendingFrame);
-
- m_chromiumCompositorData->frameDevicePixelRatio = frame.metadata.device_scale_factor;
- m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData);
- m_chromiumCompositorData->frameData = std::move(frame);
- m_havePendingFrame = true;
+ DCHECK(!m_submitCallback);
- // Tell viewDelegate to call updatePaintNode() soon.
- m_viewDelegate->update();
+ m_pendingFrame = std::move(frame);
+ m_submitCallback = std::move(callback);
+ m_resourceTracker->submitResources(
+ m_pendingFrame,
+ base::BindOnce(&Compositor::runSubmitCallback, base::Unretained(this)));
}
-QSGNode *Compositor::updatePaintNode(QSGNode *oldNode)
+QSGNode *Compositor::updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *viewDelegate)
{
// DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
//
@@ -129,30 +121,42 @@ QSGNode *Compositor::updatePaintNode(QSGNode *oldNode)
if (!frameNode)
frameNode = new DelegatedFrameNode;
- frameNode->commit(m_chromiumCompositorData.data(), &m_resourcesToRelease, m_viewDelegate);
-
- if (m_havePendingFrame) {
- m_havePendingFrame = false;
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Compositor::notifyFrameCommitted, m_weakPtrFactory.GetWeakPtr()));
+ if (!m_updatePaintNodeShouldCommit) {
+ frameNode->commit(m_committedFrame, viz::CompositorFrame(), m_resourceTracker.get(), viewDelegate);
+ return frameNode;
}
- if (m_chromiumCompositorData->frameData.metadata.request_presentation_feedback)
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(&Compositor::sendPresentationFeedback, m_weakPtrFactory.GetWeakPtr(), m_chromiumCompositorData->frameData.metadata.frame_token));
+ m_updatePaintNodeShouldCommit = false;
+
+ if (m_committedFrame.metadata.request_presentation_feedback)
+ m_taskRunner->PostTask(FROM_HERE,
+ base::BindOnce(&Compositor::sendPresentationFeedback, m_weakPtrFactory.GetWeakPtr(),
+ m_committedFrame.metadata.frame_token));
+ m_resourceTracker->commitResources();
+ frameNode->commit(m_pendingFrame, m_committedFrame, m_resourceTracker.get(), viewDelegate);
+ m_committedFrame = std::move(m_pendingFrame);
+ m_pendingFrame = viz::CompositorFrame();
+
+ m_taskRunner->PostTask(FROM_HERE,
+ base::BindOnce(&Compositor::notifyFrameCommitted, m_weakPtrFactory.GetWeakPtr()));
return frameNode;
}
+void Compositor::runSubmitCallback()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ m_updatePaintNodeShouldCommit = true;
+ std::move(m_submitCallback).Run();
+}
+
void Compositor::notifyFrameCommitted()
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
m_beginFrameSource->DidFinishFrame(this);
if (m_frameSinkClient)
- m_frameSinkClient->DidReceiveCompositorFrameAck(m_resourcesToRelease);
- m_resourcesToRelease.clear();
+ m_frameSinkClient->DidReceiveCompositorFrameAck(m_resourceTracker->returnResources());
}
void Compositor::sendPresentationFeedback(uint frame_token)
@@ -165,7 +169,7 @@ bool Compositor::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs &args)
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- m_view->OnBeginFrame(args.frame_time);
+ ProgressFlingIfNeeded(m_host, args.frame_time);
m_beginFrameSource->OnUpdateVSyncParameters(args.frame_time, args.interval);
if (m_frameSinkClient)
m_frameSinkClient->OnBeginFrame(args);
diff --git a/src/core/compositor.h b/src/core/compositor/compositor.h
index 7d7db5d04..69f4a530c 100644
--- a/src/core/compositor.h
+++ b/src/core/compositor/compositor.h
@@ -42,6 +42,10 @@
#include <base/memory/weak_ptr.h>
#include <components/viz/common/frame_sinks/begin_frame_source.h>
+#include <components/viz/common/quads/compositor_frame.h>
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qshareddata.h>
#include <QtCore/qglobal.h>
#include <QtCore/qshareddata.h>
@@ -50,8 +54,10 @@ QT_BEGIN_NAMESPACE
class QSGNode;
QT_END_NAMESPACE
+namespace content {
+class RenderWidgetHost;
+}
namespace viz {
-class CompositorFrame;
struct ReturnedResource;
namespace mojom {
class CompositorFrameSinkClient;
@@ -60,9 +66,8 @@ class CompositorFrameSinkClient;
namespace QtWebEngineCore {
-class RenderWidgetHostViewQt;
+class CompositorResourceTracker;
class RenderWidgetHostViewQtDelegate;
-class ChromiumCompositorData;
// Receives viz::CompositorFrames from child compositors and provides QSGNodes
// to the Qt Quick renderer.
@@ -72,10 +77,10 @@ class ChromiumCompositorData;
// Step 1. A new CompositorFrame is received from child compositors and handed
// off to submitFrame(). The new frame will start off in a pending state.
//
-// Step 2. Once the new frame is ready to be rendered, Compositor will call
-// update() on the delegate.
+// Step 2. Once the new frame is ready to be rendered, Compositor will notify
+// the client by running the callback given to submitFrame().
//
-// Step 3. Once the delegate is ready to render, updatePaintNode() should be
+// Step 3. Once the client is ready to render, updatePaintNode() should be
// called to receive the scene graph for the new frame. This call will commit
// the pending frame. Until the next frame is ready, all subsequent calls to
// updatePaintNode() will keep using this same committed frame.
@@ -85,18 +90,17 @@ class ChromiumCompositorData;
class Compositor final : private viz::BeginFrameObserverBase
{
public:
- explicit Compositor(RenderWidgetHostViewQt *hostView);
+ explicit Compositor(content::RenderWidgetHost *host);
~Compositor() override;
- void setViewDelegate(RenderWidgetHostViewQtDelegate *viewDelegate);
void setFrameSinkClient(viz::mojom::CompositorFrameSinkClient *frameSinkClient);
void setNeedsBeginFrames(bool needsBeginFrames);
- void submitFrame(viz::CompositorFrame frame);
-
- QSGNode *updatePaintNode(QSGNode *oldNode);
+ void submitFrame(viz::CompositorFrame frame, base::OnceClosure callback);
+ QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *viewDelegate);
private:
+ void runSubmitCallback();
void notifyFrameCommitted();
void sendPresentationFeedback(uint frame_token);
@@ -104,15 +108,17 @@ private:
bool OnBeginFrameDerivedImpl(const viz::BeginFrameArgs &args) override;
void OnBeginFrameSourcePausedChanged(bool paused) override;
- std::vector<viz::ReturnedResource> m_resourcesToRelease;
- QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData;
- RenderWidgetHostViewQt *m_view;
- RenderWidgetHostViewQtDelegate *m_viewDelegate = nullptr;
+ viz::CompositorFrame m_committedFrame;
+ viz::CompositorFrame m_pendingFrame;
+ base::OnceClosure m_submitCallback;
+ std::unique_ptr<CompositorResourceTracker> m_resourceTracker;
+ content::RenderWidgetHost *m_host;
std::unique_ptr<viz::SyntheticBeginFrameSource> m_beginFrameSource;
viz::mojom::CompositorFrameSinkClient *m_frameSinkClient = nullptr;
- bool m_havePendingFrame = false;
+ bool m_updatePaintNodeShouldCommit = false;
bool m_needsBeginFrames = false;
+ scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner;
base::WeakPtrFactory<Compositor> m_weakPtrFactory{this};
DISALLOW_COPY_AND_ASSIGN(Compositor);
diff --git a/src/core/compositor/compositor_resource.h b/src/core/compositor/compositor_resource.h
new file mode 100644
index 000000000..c40ce3d5e
--- /dev/null
+++ b/src/core/compositor/compositor_resource.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COMPOSITOR_RESOURCE_H
+#define COMPOSITOR_RESOURCE_H
+
+#include <base/memory/ref_counted.h>
+#include <components/viz/common/resources/transferable_resource.h>
+
+#include <QtCore/qglobal.h>
+#include <QtGui/qtgui-config.h>
+
+#if QT_CONFIG(opengl)
+# include "compositor_resource_fence.h"
+#endif
+
+namespace viz {
+class SharedBitmap;
+} // namespace viz
+
+namespace QtWebEngineCore {
+
+using CompositorResourceId = quint32;
+
+// A resource (OpenGL texture or software shared bitmap).
+//
+// - Created by the CompositorResourceTracker from a newly submitted
+// CompositorFrame's resource_list.
+//
+// - Until the frame is committed, its resources are in a 'pending' state and
+// are inaccessible from outside the CompositorResourceTracker.
+//
+// - Once the frame is committed, its resources can be found via
+// CompositorResourceTracker::findResource.
+//
+// - A committed resource's fields may not be updated and are safe to use from
+// other threads without synchronization (unless noted otherwise).
+struct CompositorResource : viz::TransferableResource
+{
+ CompositorResource(const viz::TransferableResource &tr) : viz::TransferableResource(tr) {}
+
+ // Counts the number of times this resource has been encountered in
+ // CompositorFrames' resource lists.
+ //
+ // Corresponds to viz::ReturnedResource::count.
+ //
+ // Updated by CompositorResourceTracker on UI thread.
+ int import_count = 1;
+
+ // Identifies the last frame that needed this resource. Used by
+ // CompositorResourceTracker to return unused resources back to child
+ // compositors.
+ //
+ // Updated by CompositorResourceTracker on UI thread.
+ quint32 last_used_for_frame = 0;
+
+ // Bitmap (if is_software).
+ std::unique_ptr<viz::SharedBitmap> bitmap;
+
+#if QT_CONFIG(opengl)
+ // OpenGL texture id (if !is_software).
+ quint32 texture_id = 0;
+
+ // Should be waited on before using the texture (non-null if !is_software).
+ scoped_refptr<CompositorResourceFence> texture_fence;
+#endif // QT_CONFIG(opengl)
+};
+
+inline bool operator<(const CompositorResource &r1, const CompositorResource &r2)
+{
+ return r1.id < r2.id;
+}
+
+inline bool operator<(const CompositorResource &r, CompositorResourceId id)
+{
+ return r.id < id;
+}
+
+inline bool operator<(CompositorResourceId id, const CompositorResource &r)
+{
+ return id < r.id;
+}
+
+} // namespace QtWebEngineCore
+
+#endif // !COMPOSITOR_RESOURCE_H
diff --git a/src/core/compositor/compositor_resource_fence.cpp b/src/core/compositor/compositor_resource_fence.cpp
new file mode 100644
index 000000000..7fc5fbfb2
--- /dev/null
+++ b/src/core/compositor/compositor_resource_fence.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "compositor_resource_fence.h"
+
+#include "ui/gl/gl_context.h"
+
+#include <QtGui/qopenglcontext.h>
+
+#ifndef GL_TIMEOUT_IGNORED
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#endif
+
+namespace QtWebEngineCore {
+
+void CompositorResourceFence::wait()
+{
+ if (!m_sync)
+ return;
+
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ Q_ASSERT(context);
+
+ // Chromium uses its own GL bindings and stores in in thread local storage.
+ // For that reason, let chromium_gpu_helper.cpp contain the producing code that will run in the Chromium
+ // GPU thread, and put the sync consuming code here that will run in the QtQuick SG or GUI thread.
+ switch (m_sync.type) {
+ case gl::TransferableFence::NoSync:
+ break;
+ case gl::TransferableFence::EglSync:
+#ifdef EGL_KHR_reusable_sync
+ {
+ static bool resolved = false;
+ static PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR = 0;
+
+ if (!resolved) {
+ if (gl::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync"))
+ eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)context->getProcAddress("eglClientWaitSyncKHR");
+ resolved = true;
+ }
+
+ if (eglClientWaitSyncKHR)
+ // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync.
+ eglClientWaitSyncKHR(m_sync.egl.display, m_sync.egl.sync, 0, EGL_FOREVER_KHR);
+ }
+#endif
+ break;
+ case gl::TransferableFence::ArbSync:
+ typedef void (QOPENGLF_APIENTRYP WaitSyncPtr)(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ static WaitSyncPtr glWaitSync_ = 0;
+ if (!glWaitSync_) {
+ glWaitSync_ = (WaitSyncPtr)context->getProcAddress("glWaitSync");
+ Q_ASSERT(glWaitSync_);
+ }
+ glWaitSync_(m_sync.arb.sync, 0, GL_TIMEOUT_IGNORED);
+ break;
+ }
+
+ release();
+}
+
+void CompositorResourceFence::release()
+{
+ if (!m_sync)
+ return;
+
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ if (!context)
+ return;
+
+ // Chromium uses its own GL bindings and stores in in thread local storage.
+ // For that reason, let chromium_gpu_helper.cpp contain the producing code that will run in the Chromium
+ // GPU thread, and put the sync consuming code here that will run in the QtQuick SG or GUI thread.
+ switch (m_sync.type) {
+ case gl::TransferableFence::NoSync:
+ break;
+ case gl::TransferableFence::EglSync:
+#ifdef EGL_KHR_reusable_sync
+ {
+ static bool resolved = false;
+ static PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = 0;
+
+ if (!resolved) {
+ if (gl::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync"))
+ eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)context->getProcAddress("eglDestroySyncKHR");
+ resolved = true;
+ }
+
+ if (eglDestroySyncKHR) {
+ // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync.
+ eglDestroySyncKHR(m_sync.egl.display, m_sync.egl.sync);
+ m_sync.reset();
+ }
+ }
+#endif
+ break;
+ case gl::TransferableFence::ArbSync:
+ typedef void (QOPENGLF_APIENTRYP DeleteSyncPtr)(GLsync sync);
+ static DeleteSyncPtr glDeleteSync_ = 0;
+ if (!glDeleteSync_) {
+ glDeleteSync_ = (DeleteSyncPtr)context->getProcAddress("glDeleteSync");
+ Q_ASSERT(glDeleteSync_);
+ }
+ glDeleteSync_(m_sync.arb.sync);
+ m_sync.reset();
+ break;
+ }
+ // If Chromium was able to create a sync, we should have been able to handle its type here too.
+ Q_ASSERT(!m_sync);
+}
+
+// static
+scoped_refptr<CompositorResourceFence> CompositorResourceFence::create()
+{
+ if (gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) {
+ std::unique_ptr<gl::GLFence> glFence{gl::GLFence::Create()};
+ return base::MakeRefCounted<CompositorResourceFence>(glFence->Transfer());
+ }
+ return nullptr;
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/net/url_request_qrc_job_qt.h b/src/core/compositor/compositor_resource_fence.h
index 11c130693..1c2ea3695 100644
--- a/src/core/net/url_request_qrc_job_qt.h
+++ b/src/core/compositor/compositor_resource_fence.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -37,40 +37,35 @@
**
****************************************************************************/
-#ifndef URL_REQUEST_QRC_JOB_QT_H_
-#define URL_REQUEST_QRC_JOB_QT_H_
+#ifndef COMPOSITOR_RESOURCE_FENCE_H
+#define COMPOSITOR_RESOURCE_FENCE_H
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_job.h"
-
-#include <QFile>
+#include <base/memory/ref_counted.h>
+#include <ui/gl/gl_fence.h>
namespace QtWebEngineCore {
-// A request job that handles reading qrc file URLs
-class URLRequestQrcJobQt : public net::URLRequestJob {
-
+// Sync object created on GPU thread and consumed on render thread.
+class CompositorResourceFence final : public base::RefCountedThreadSafe<CompositorResourceFence>
+{
public:
- URLRequestQrcJobQt(net::URLRequest *request, net::NetworkDelegate *networkDelegate);
- void Start() override;
- void Kill() override;
- int ReadRawData(net::IOBuffer* buf, int buf_size) override;;
- bool GetMimeType(std::string *mimeType) const override;
+ REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
-protected:
- virtual ~URLRequestQrcJobQt();
- // Get file mime type and try open file on a background thread.
- void startGetHead();
+ CompositorResourceFence() {}
+ CompositorResourceFence(const gl::TransferableFence &sync) : m_sync(sync) {};
+ ~CompositorResourceFence() { release(); }
-private:
- qint64 m_remainingBytes;
- QFile m_file;
- std::string m_mimeType;
- base::WeakPtrFactory<URLRequestQrcJobQt> m_weakFactory;
+ // May be used only by Qt Quick render thread.
+ void wait();
+ void release();
- DISALLOW_COPY_AND_ASSIGN(URLRequestQrcJobQt);
+ // May be used only by GPU thread.
+ static scoped_refptr<CompositorResourceFence> create();
+
+private:
+ gl::TransferableFence m_sync;
};
} // namespace QtWebEngineCore
-#endif // URL_REQUEST_QRC_JOB_QT_H_
+#endif // !COMPOSITOR_RESOURCE_FENCE_H
diff --git a/src/core/compositor/compositor_resource_tracker.cpp b/src/core/compositor/compositor_resource_tracker.cpp
new file mode 100644
index 000000000..6530f3249
--- /dev/null
+++ b/src/core/compositor/compositor_resource_tracker.cpp
@@ -0,0 +1,259 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "compositor_resource_tracker.h"
+
+#include "chromium_gpu_helper.h"
+#include "render_widget_host_view_qt_delegate.h"
+#include "web_engine_context.h"
+
+#include "base/message_loop/message_loop.h"
+#include "base/task/post_task.h"
+#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/resources/returned_resource.h"
+#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/gpu/content_gpu_client.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/sync_point_manager.h"
+
+namespace QtWebEngineCore {
+
+CompositorResourceTracker::CompositorResourceTracker()
+{}
+
+CompositorResourceTracker::~CompositorResourceTracker()
+{}
+
+void CompositorResourceTracker::submitResources(const viz::CompositorFrame &frame, base::OnceClosure callback)
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(!m_submitCallback);
+ DCHECK(m_pendingResources.empty());
+ DCHECK(m_pendingImports.empty());
+ DCHECK(m_pendingResourceUpdates == 0);
+
+ m_submitCallback = std::move(callback);
+
+ m_pendingResources.reserve(frame.resource_list.size());
+ m_pendingImports.reserve(frame.resource_list.size());
+
+ for (const viz::TransferableResource &transferableResource : frame.resource_list) {
+ auto it = m_committedResources.find(transferableResource.id);
+ if (it != m_committedResources.end())
+ m_pendingImports.push_back(&*it);
+ else
+ m_pendingResources.emplace_back(transferableResource);
+ }
+
+ if (m_pendingResources.empty()) {
+ scheduleRunSubmitCallback();
+ return;
+ }
+
+ m_pendingResourceUpdates = m_pendingResources.size();
+
+ std::vector<CompositorResource *> batch;
+ batch.reserve(m_pendingResources.size());
+
+ for (CompositorResource &resource : m_pendingResources) {
+ if (resource.is_software)
+ updateBitmap(&resource);
+ else if (!scheduleUpdateMailbox(&resource))
+ batch.push_back(&resource);
+ }
+
+ if (!batch.empty())
+ scheduleUpdateMailboxes(std::move(batch));
+}
+
+void CompositorResourceTracker::commitResources()
+{
+ // DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ //
+ // This might be called from a Qt Quick render thread, but the UI thread
+ // will still be blocked for the duration of this call.
+
+ DCHECK(m_pendingResourceUpdates == 0);
+
+ for (CompositorResource *resource : m_pendingImports)
+ resource->import_count++;
+ m_pendingImports.clear();
+
+ m_committedResources.insert(std::make_move_iterator(m_pendingResources.begin()),
+ std::make_move_iterator(m_pendingResources.end()));
+ m_pendingResources.clear();
+
+ ++m_committedFrameId;
+}
+
+std::vector<viz::ReturnedResource> CompositorResourceTracker::returnResources()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ std::vector<viz::ReturnedResource> returnedResources;
+ base::EraseIf(m_committedResources, [&](const CompositorResource &resource) {
+ if (resource.last_used_for_frame != m_committedFrameId) {
+ viz::ReturnedResource returnedResource;
+ returnedResource.id = resource.id;
+ returnedResource.count = resource.import_count;
+ returnedResources.push_back(std::move(returnedResource));
+ return true;
+ }
+ return false;
+ });
+ return returnedResources;
+}
+
+const CompositorResource *CompositorResourceTracker::findResource(CompositorResourceId id) const
+{
+ auto it = m_committedResources.find(id);
+ DCHECK(it != m_committedResources.end());
+
+ const_cast<CompositorResource &>(*it).last_used_for_frame = m_committedFrameId;
+
+ return &*it;
+}
+
+void CompositorResourceTracker::updateBitmap(CompositorResource *resource)
+{
+ content::BrowserMainLoop *browserMainLoop = content::BrowserMainLoop::GetInstance();
+ viz::ServerSharedBitmapManager *bitmapManager = browserMainLoop->GetServerSharedBitmapManager();
+
+ resource->bitmap = bitmapManager->GetSharedBitmapFromId(
+ resource->size,
+ viz::BGRA_8888,
+ resource->mailbox_holder.mailbox);
+
+ if (--m_pendingResourceUpdates == 0)
+ scheduleRunSubmitCallback();
+}
+
+quint32 CompositorResourceTracker::consumeMailbox(const gpu::MailboxHolder &mailboxHolder)
+{
+#if QT_CONFIG(opengl)
+ gpu::MailboxManager *mailboxManager = mailbox_manager();
+ DCHECK(mailboxManager);
+ if (mailboxHolder.sync_token.HasData())
+ mailboxManager->PullTextureUpdates(mailboxHolder.sync_token);
+ return service_id(mailboxManager->ConsumeTexture(mailboxHolder.mailbox));
+#else
+ NOTREACHED();
+#endif // QT_CONFIG(OPENGL)
+}
+
+bool CompositorResourceTracker::scheduleUpdateMailbox(CompositorResource *resource)
+{
+#if QT_CONFIG(opengl)
+ gpu::SyncPointManager *syncPointManager = WebEngineContext::syncPointManager();
+ DCHECK(syncPointManager);
+ return syncPointManager->WaitOutOfOrder(
+ resource->mailbox_holder.sync_token,
+ base::BindOnce(&CompositorResourceTracker::updateMailbox,
+ m_weakPtrFactory.GetWeakPtr(),
+ resource));
+#else
+ NOTREACHED();
+#endif // QT_CONFIG(OPENGL)
+}
+
+void CompositorResourceTracker::updateMailbox(CompositorResource *resource)
+{
+#if QT_CONFIG(opengl)
+ resource->texture_id = consumeMailbox(resource->mailbox_holder);
+ resource->texture_fence = CompositorResourceFence::create();
+
+ if (--m_pendingResourceUpdates == 0)
+ scheduleRunSubmitCallback();
+#else
+ NOTREACHED();
+#endif // QT_CONFIG(OPENGL)
+}
+
+void CompositorResourceTracker::scheduleUpdateMailboxes(std::vector<CompositorResource *> resources)
+{
+#if QT_CONFIG(opengl)
+ scoped_refptr<base::SingleThreadTaskRunner> gpuTaskRunner = gpu_task_runner();
+ DCHECK(gpuTaskRunner);
+ gpuTaskRunner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CompositorResourceTracker::updateMailboxes,
+ m_weakPtrFactory.GetWeakPtr(),
+ std::move(resources)));
+#else
+ NOTREACHED();
+#endif // QT_CONFIG(OPENGL)
+}
+
+void CompositorResourceTracker::updateMailboxes(std::vector<CompositorResource *> resources)
+{
+#if QT_CONFIG(opengl)
+ for (CompositorResource *resource : resources)
+ resource->texture_id = consumeMailbox(resource->mailbox_holder);
+
+ scoped_refptr<CompositorResourceFence> fence = CompositorResourceFence::create();
+
+ for (CompositorResource *resource : resources)
+ resource->texture_fence = fence;
+
+ if ((m_pendingResourceUpdates -= resources.size()) == 0)
+ scheduleRunSubmitCallback();
+#else
+ NOTREACHED();
+#endif // QT_CONFIG(OPENGL)
+}
+
+void CompositorResourceTracker::scheduleRunSubmitCallback()
+{
+ base::PostTaskWithTraits(
+ FROM_HERE, { content::BrowserThread::UI },
+ base::BindOnce(&CompositorResourceTracker::runSubmitCallback,
+ m_weakPtrFactory.GetWeakPtr()));
+}
+
+void CompositorResourceTracker::runSubmitCallback()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ std::move(m_submitCallback).Run();
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/compositor/compositor_resource_tracker.h b/src/core/compositor/compositor_resource_tracker.h
new file mode 100644
index 000000000..887309395
--- /dev/null
+++ b/src/core/compositor/compositor_resource_tracker.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COMPOSITOR_RESOURCE_TRACKER_H
+#define COMPOSITOR_RESOURCE_TRACKER_H
+
+#include "compositor_resource.h"
+#include "locked_ptr.h"
+
+#include <base/callback.h>
+#include <base/containers/flat_set.h>
+
+#include <atomic>
+#include <vector>
+
+namespace viz {
+class CompositorFrame;
+struct ReturnedResource;
+} // namespace viz
+
+namespace gpu {
+struct MailboxHolder;
+} // namespace gpu
+
+namespace QtWebEngineCore {
+
+// Ensures resources are not used before they are ready.
+//
+// The life cycle of a frame's resources:
+//
+// Step 1. A new CompositorFrame is received and given to submitResources().
+// The frame's resources will extracted and initialized to a pending state.
+//
+// Step 2. Once the new resources are ready to be committed,
+// CompositorResourceTracker will notify the client by running the callback
+// given to submitResources().
+//
+// Step 3. Once the client is ready to render, commitResources() should be
+// called. This will commit all the pending resources, making them available
+// via findResource().
+//
+// Step 4. Once all the resources have been used (via findResource()),
+// returnResources() may be called to return a list of all the resources which
+// were *not* used since the last commitResources(). Go to step 1.
+class CompositorResourceTracker final
+{
+public:
+ CompositorResourceTracker();
+ ~CompositorResourceTracker();
+
+ void submitResources(const viz::CompositorFrame &frame, base::OnceClosure callback);
+ void commitResources();
+ std::vector<viz::ReturnedResource> returnResources();
+
+ // The returned pointer is invalidated by the next call to commitFrame() or
+ // returnResources(). It should therefore not be stored in data structures
+ // but used immediately.
+ //
+ // Do not ask for resources which do not exist.
+ const CompositorResource *findResource(CompositorResourceId id) const;
+
+private:
+ void updateBitmap(CompositorResource *resource);
+
+ quint32 consumeMailbox(const gpu::MailboxHolder &mailboxHolder);
+
+ bool scheduleUpdateMailbox(CompositorResource *resource);
+ void updateMailbox(CompositorResource *resource);
+
+ void scheduleUpdateMailboxes(std::vector<CompositorResource *> resources);
+ void updateMailboxes(std::vector<CompositorResource *> resources);
+
+ void scheduleRunSubmitCallback();
+ void runSubmitCallback();
+
+ base::flat_set<CompositorResource> m_committedResources;
+ std::vector<CompositorResource> m_pendingResources;
+ std::vector<CompositorResource *> m_pendingImports;
+ base::OnceClosure m_submitCallback;
+ std::atomic<size_t> m_pendingResourceUpdates{0};
+ quint32 m_committedFrameId = 0;
+
+ base::LockedPtrFactory<CompositorResourceTracker> m_weakPtrFactory{this};
+
+ DISALLOW_COPY_AND_ASSIGN(CompositorResourceTracker);
+};
+
+} // namespace QtWebEngineCore
+
+#endif // !COMPOSITOR_RESOURCE_TRACKER_H
diff --git a/src/core/compositor/content_gpu_client_qt.cpp b/src/core/compositor/content_gpu_client_qt.cpp
new file mode 100644
index 000000000..f934979a0
--- /dev/null
+++ b/src/core/compositor/content_gpu_client_qt.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "content_gpu_client_qt.h"
+
+#include "web_engine_context.h"
+
+namespace QtWebEngineCore {
+
+ContentGpuClientQt::ContentGpuClientQt()
+{
+}
+
+ContentGpuClientQt::~ContentGpuClientQt()
+{
+}
+
+gpu::SyncPointManager *ContentGpuClientQt::GetSyncPointManager()
+{
+ return WebEngineContext::syncPointManager();
+}
+
+} // namespace
diff --git a/src/core/compositor/content_gpu_client_qt.h b/src/core/compositor/content_gpu_client_qt.h
new file mode 100644
index 000000000..d7ad43881
--- /dev/null
+++ b/src/core/compositor/content_gpu_client_qt.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef CONTENT_GPU_CLIENT_QT_H
+#define CONTENT_GPU_CLIENT_QT_H
+
+#include "content/public/gpu/content_gpu_client.h"
+
+namespace QtWebEngineCore {
+
+class ContentGpuClientQt : public content::ContentGpuClient {
+public:
+ explicit ContentGpuClientQt();
+ ~ContentGpuClientQt() override;
+
+ // content::ContentGpuClient implementation.
+ gpu::SyncPointManager *GetSyncPointManager() override;
+};
+
+}
+
+#endif // CONTENT_GPU_CLIENT_QT_H
diff --git a/src/core/delegated_frame_node.cpp b/src/core/compositor/delegated_frame_node.cpp
index 8ac82dbf1..e2b6714a1 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/compositor/delegated_frame_node.cpp
@@ -49,17 +49,14 @@
#include "delegated_frame_node.h"
#include "chromium_gpu_helper.h"
-#include "ozone/gl_surface_qt.h"
#include "stream_video_node.h"
#include "type_conversion.h"
#include "yuv_video_node.h"
+#include "compositor_resource_tracker.h"
#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "cc/base/math_util.h"
#include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "components/viz/common/quads/debug_border_draw_quad.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
@@ -68,14 +65,8 @@
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
-#include "components/viz/common/resources/returned_resource.h"
-#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/service/display/bsp_tree.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
-#include "content/browser/browser_main_loop.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_fence.h"
#ifndef QT_NO_OPENGL
# include <QOpenGLContext>
@@ -93,10 +84,6 @@
#include <EGL/eglext.h>
#endif
-#ifndef GL_TIMEOUT_IGNORED
-#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
-#endif
-
#ifndef GL_TEXTURE_RECTANGLE
#define GL_TEXTURE_RECTANGLE 0x84F5
#endif
@@ -131,7 +118,7 @@ namespace QtWebEngineCore {
#ifndef QT_NO_OPENGL
class MailboxTexture : public QSGTexture, protected QOpenGLFunctions {
public:
- MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QSize textureSize);
+ MailboxTexture(const CompositorResource *resource, bool hasAlphaChannel, int target = -1);
~MailboxTexture();
// QSGTexture:
int textureId() const override { return m_textureId; }
@@ -140,14 +127,9 @@ public:
bool hasMipmaps() const override { return false; }
void bind() override;
- void setHasAlphaChannel(bool hasAlpha) { m_hasAlpha = hasAlpha; }
- gpu::MailboxHolder &mailboxHolder() { return m_mailboxHolder; }
- void fetchTexture(gpu::MailboxManager *mailboxManager);
- void setTarget(GLenum target);
-
private:
- gpu::MailboxHolder m_mailboxHolder;
int m_textureId;
+ scoped_refptr<CompositorResourceFence> m_fence;
QSize m_textureSize;
bool m_hasAlpha;
GLenum m_target;
@@ -160,20 +142,6 @@ private:
friend class DelegatedFrameNode;
};
#endif // QT_NO_OPENGL
-class ResourceHolder {
-public:
- ResourceHolder(const viz::TransferableResource &resource);
- QSharedPointer<QSGTexture> initTexture(bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0);
- QSGTexture *texture() const { return m_texture.data(); }
- viz::ReturnedResource returnResource();
- void incImportCount() { ++m_importCount; }
- bool needsToFetch() const { return !m_resource.is_software && m_texture && !m_texture.data()->textureId(); }
-
-private:
- QWeakPointer<QSGTexture> m_texture;
- viz::TransferableResource m_resource;
- int m_importCount;
-};
class RectClipNode : public QSGClipNode
{
@@ -443,7 +411,9 @@ static QSGNode *buildLayerChain(QSGNode *chainParent, const viz::SharedQuadState
}
if (!layerState->quad_to_target_transform.IsIdentity()) {
QSGTransformNode *transformNode = new QSGTransformNode;
- transformNode->setMatrix(toQt(layerState->quad_to_target_transform.matrix()));
+ QMatrix4x4 qMatrix;
+ convertToQt(layerState->quad_to_target_transform.matrix(), qMatrix);
+ transformNode->setMatrix(qMatrix);
layerChain->appendChildNode(transformNode);
layerChain = transformNode;
}
@@ -457,99 +427,12 @@ static QSGNode *buildLayerChain(QSGNode *chainParent, const viz::SharedQuadState
}
#ifndef QT_NO_OPENGL
-static void waitChromiumSync(gl::TransferableFence *sync)
-{
- // Chromium uses its own GL bindings and stores in in thread local storage.
- // For that reason, let chromium_gpu_helper.cpp contain the producing code that will run in the Chromium
- // GPU thread, and put the sync consuming code here that will run in the QtQuick SG or GUI thread.
- switch (sync->type) {
- case gl::TransferableFence::NoSync:
- break;
- case gl::TransferableFence::EglSync:
-#ifdef EGL_KHR_reusable_sync
- {
- static bool resolved = false;
- static PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR = 0;
-
- if (!resolved) {
- if (gl::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync")) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)context->getProcAddress("eglClientWaitSyncKHR");
- }
- resolved = true;
- }
-
- if (eglClientWaitSyncKHR)
- // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync.
- eglClientWaitSyncKHR(sync->egl.display, sync->egl.sync, 0, EGL_FOREVER_KHR);
- }
-#endif
- break;
- case gl::TransferableFence::ArbSync:
- typedef void (QOPENGLF_APIENTRYP WaitSyncPtr)(GLsync sync, GLbitfield flags, GLuint64 timeout);
- static WaitSyncPtr glWaitSync_ = 0;
- if (!glWaitSync_) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- glWaitSync_ = (WaitSyncPtr)context->getProcAddress("glWaitSync");
- Q_ASSERT(glWaitSync_);
- }
- glWaitSync_(sync->arb.sync, 0, GL_TIMEOUT_IGNORED);
- break;
- }
-}
-
-static void deleteChromiumSync(gl::TransferableFence *sync)
-{
- // Chromium uses its own GL bindings and stores in in thread local storage.
- // For that reason, let chromium_gpu_helper.cpp contain the producing code that will run in the Chromium
- // GPU thread, and put the sync consuming code here that will run in the QtQuick SG or GUI thread.
- switch (sync->type) {
- case gl::TransferableFence::NoSync:
- break;
- case gl::TransferableFence::EglSync:
-#ifdef EGL_KHR_reusable_sync
- {
- static bool resolved = false;
- static PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = 0;
-
- if (!resolved) {
- if (gl::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync")) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)context->getProcAddress("eglDestroySyncKHR");
- }
- resolved = true;
- }
-
- if (eglDestroySyncKHR) {
- // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync.
- eglDestroySyncKHR(sync->egl.display, sync->egl.sync);
- sync->reset();
- }
- }
-#endif
- break;
- case gl::TransferableFence::ArbSync:
- typedef void (QOPENGLF_APIENTRYP DeleteSyncPtr)(GLsync sync);
- static DeleteSyncPtr glDeleteSync_ = 0;
- if (!glDeleteSync_) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- glDeleteSync_ = (DeleteSyncPtr)context->getProcAddress("glDeleteSync");
- Q_ASSERT(glDeleteSync_);
- }
- glDeleteSync_(sync->arb.sync);
- sync->reset();
- break;
- }
- // If Chromium was able to create a sync, we should have been able to handle its type here too.
- Q_ASSERT(!*sync);
-}
-
-MailboxTexture::MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QSize textureSize)
- : m_mailboxHolder(mailboxHolder)
- , m_textureId(0)
- , m_textureSize(textureSize)
- , m_hasAlpha(false)
- , m_target(GL_TEXTURE_2D)
+MailboxTexture::MailboxTexture(const CompositorResource *resource, bool hasAlphaChannel, int target)
+ : m_textureId(resource->texture_id)
+ , m_fence(resource->texture_fence)
+ , m_textureSize(toQt(resource->size))
+ , m_hasAlpha(hasAlphaChannel)
+ , m_target(target >= 0 ? target : GL_TEXTURE_2D)
#if defined(USE_OZONE)
, m_ownsTexture(false)
#endif
@@ -580,6 +463,8 @@ MailboxTexture::~MailboxTexture()
void MailboxTexture::bind()
{
+ if (m_fence)
+ m_fence->wait();
glBindTexture(m_target, m_textureId);
#ifdef Q_OS_QNX
if (m_target == GL_TEXTURE_EXTERNAL_OES) {
@@ -596,96 +481,7 @@ void MailboxTexture::bind()
}
#endif
}
-
-void MailboxTexture::setTarget(GLenum target)
-{
- m_target = target;
-}
-
-void MailboxTexture::fetchTexture(gpu::MailboxManager *mailboxManager)
-{
- gpu::TextureBase *tex = ConsumeTexture(mailboxManager, m_target, m_mailboxHolder.mailbox);
-
- // The texture might already have been deleted (e.g. when navigating away from a page).
- if (tex) {
- m_textureId = service_id(tex);
-#ifdef Q_OS_QNX
- if (m_target == GL_TEXTURE_EXTERNAL_OES) {
- m_eglStreamData = eglstream_connect_consumer(tex);
- }
-#endif
- }
-}
-#endif //QT_NO_OPENGL
-
-ResourceHolder::ResourceHolder(const viz::TransferableResource &resource)
- : m_resource(resource)
- , m_importCount(1)
-{
-}
-
-QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, RenderWidgetHostViewQtDelegate *apiDelegate)
-{
- QSharedPointer<QSGTexture> texture = m_texture.toStrongRef();
- if (!texture) {
- if (m_resource.is_software) {
- Q_ASSERT(apiDelegate);
- std::unique_ptr<viz::SharedBitmap> sharedBitmap =
- content::BrowserMainLoop::GetInstance()->GetServerSharedBitmapManager()->GetSharedBitmapFromId(
- m_resource.size, viz::BGRA_8888, m_resource.mailbox_holder.mailbox);
- // QSG interprets QImage::hasAlphaChannel meaning that a node should enable blending
- // to draw it but Chromium keeps this information in the quads.
- // The input format is currently always Format_ARGB32_Premultiplied, so assume that all
- // alpha bytes are 0xff if quads aren't requesting blending and avoid the conversion
- // from Format_ARGB32_Premultiplied to Format_RGB32 just to get hasAlphaChannel to
- // return false.
- QImage::Format format = quadNeedsBlending ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
- QImage image = sharedBitmap
- ? QImage(sharedBitmap->pixels(), m_resource.size.width(), m_resource.size.height(), format)
- : QImage(m_resource.size.width(), m_resource.size.height(), format);
- texture.reset(apiDelegate->createTextureFromImage(image.copy()));
- } else {
-#ifndef QT_NO_OPENGL
- texture.reset(new MailboxTexture(m_resource.mailbox_holder, toQt(m_resource.size)));
- static_cast<MailboxTexture *>(texture.data())->setHasAlphaChannel(quadNeedsBlending);
-#else
- Q_UNREACHABLE();
-#endif
- }
- if (m_resource.filter == GL_NEAREST)
- texture->setFiltering(QSGTexture::Nearest);
- else if (m_resource.filter == GL_LINEAR)
- texture->setFiltering(QSGTexture::Linear);
- else {
- // Depends on qtdeclarative fix, see QTBUG-71322
-#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 1)
- texture->setFiltering(QSGTexture::Linear);
-#else
- texture->setFiltering(QSGTexture::Nearest);
-#endif
- }
- m_texture = texture;
- }
- // All quads using a resource should request the same blending state.
- Q_ASSERT(texture->hasAlphaChannel() || !quadNeedsBlending);
- return texture;
-}
-
-viz::ReturnedResource ResourceHolder::returnResource()
-{
- viz::ReturnedResource returned;
- // The ResourceProvider ensures that the resource isn't used by the parent compositor's GL
- // context in the GPU process by inserting a sync point to be waited for by the child
- // compositor's GL context. We don't need this since we are triggering the delegated frame
- // ack directly from our rendering thread. At this point (in updatePaintNode) we know that
- // a frame that was compositing any of those resources has already been swapped and we thus
- // don't need to use this mechanism.
- returned.id = m_resource.id;
- returned.count = m_importCount;
- m_importCount = 0;
- return returned;
-}
-
+#endif // !QT_NO_OPENGL
RectClipNode::RectClipNode(const QRectF &rect)
: m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
@@ -697,9 +493,8 @@ RectClipNode::RectClipNode(const QRectF &rect)
}
DelegatedFrameNode::DelegatedFrameNode()
- : m_numPendingSyncPoints(0)
#if defined(USE_OZONE) && !defined(QT_NO_OPENGL)
- , m_contextShared(true)
+ : m_contextShared(true)
#endif
{
setFlag(UsePreprocess);
@@ -725,22 +520,6 @@ DelegatedFrameNode::~DelegatedFrameNode()
void DelegatedFrameNode::preprocess()
{
-#ifndef QT_NO_OPENGL
- // With the threaded render loop the GUI thread has been unlocked at this point.
- // We can now wait for the Chromium GPU thread to produce textures that will be
- // rendered on our quads and fetch the IDs from the mailboxes we were given.
- QList<MailboxTexture *> mailboxesToFetch;
- typedef QHash<unsigned, QSharedPointer<ResourceHolder> >::const_iterator ResourceHolderIterator;
- ResourceHolderIterator end = m_chromiumCompositorData->resourceHolders.constEnd();
- for (ResourceHolderIterator it = m_chromiumCompositorData->resourceHolders.constBegin(); it != end ; ++it) {
- if ((*it)->needsToFetch())
- mailboxesToFetch.append(static_cast<MailboxTexture *>((*it)->texture()));
- }
-
- if (!mailboxesToFetch.isEmpty())
- fetchAndSyncMailboxes(mailboxesToFetch);
-#endif
-
// Then render any intermediate RenderPass in order.
typedef QPair<int, QSharedPointer<QSGLayer> > Pair;
for (const Pair &pair : qAsConst(m_sgObjects.renderPassLayers)) {
@@ -767,8 +546,8 @@ static bool areSharedQuadStatesEqual(const viz::SharedQuadState *layerState,
// Compares if the frame data that we got from the Chromium Compositor is
// *structurally* equivalent to the one of the previous frame.
// If it is, we will just reuse and update the old nodes where necessary.
-static bool areRenderPassStructuresEqual(viz::CompositorFrame *frameData,
- viz::CompositorFrame *previousFrameData)
+static bool areRenderPassStructuresEqual(const viz::CompositorFrame *frameData,
+ const viz::CompositorFrame *previousFrameData)
{
if (!previousFrameData)
return false;
@@ -820,12 +599,12 @@ static bool areRenderPassStructuresEqual(viz::CompositorFrame *frameData,
return true;
}
-void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
- std::vector<viz::ReturnedResource> *resourcesToRelease,
+void DelegatedFrameNode::commit(const viz::CompositorFrame &pendingFrame,
+ const viz::CompositorFrame &committedFrame,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate)
{
- m_chromiumCompositorData = chromiumCompositorData;
- viz::CompositorFrame* frameData = &m_chromiumCompositorData->frameData;
+ const viz::CompositorFrame* frameData = &pendingFrame;
if (frameData->render_pass_list.empty())
return;
@@ -833,27 +612,11 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
// countering the scale of devicePixel-scaled tiles when rendering them
// to the final surface.
QMatrix4x4 matrix;
- const float devicePixelRatio = m_chromiumCompositorData->frameDevicePixelRatio;
+ const float devicePixelRatio = frameData->metadata.device_scale_factor;
matrix.scale(1 / devicePixelRatio, 1 / devicePixelRatio);
if (QSGTransformNode::matrix() != matrix)
setMatrix(matrix);
- QHash<unsigned, QSharedPointer<ResourceHolder> > resourceCandidates;
- qSwap(m_chromiumCompositorData->resourceHolders, resourceCandidates);
-
- // A frame's resource_list only contains the new resources to be added to the scene. Quads can
- // still reference resources that were added in previous frames. Add them to the list of
- // candidates to be picked up by quads, it's then our responsibility to return unused resources
- // to the producing child compositor.
- for (unsigned i = 0; i < frameData->resource_list.size(); ++i) {
- const viz::TransferableResource &res = frameData->resource_list.at(i);
- if (QSharedPointer<ResourceHolder> resource = resourceCandidates.value(res.id))
- resource->incImportCount();
- else
- resourceCandidates[res.id] = QSharedPointer<ResourceHolder>(new ResourceHolder(res));
- }
-
- frameData->resource_list.clear();
QScopedPointer<DelegatedNodeTreeHandler> nodeHandler;
const QSizeF viewportSizeInPt = apiDelegate->screenRect().size();
@@ -867,26 +630,22 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
// Additionally, because we clip (i.e. don't build scene graph nodes for) quads outside
// of the visible area, we also have to rebuild the tree whenever the window is resized.
const bool buildNewTree =
- !areRenderPassStructuresEqual(frameData, &m_chromiumCompositorData->previousFrameData) ||
+ !areRenderPassStructuresEqual(frameData, &committedFrame) ||
m_sceneGraphNodes.empty() ||
viewportSize != m_previousViewportSize;
- m_chromiumCompositorData->previousFrameData = viz::CompositorFrame();
- SGObjects previousSGObjects;
- QVector<QSharedPointer<QSGTexture> > textureStrongRefs;
if (buildNewTree) {
// Keep the old objects in scope to hold a ref on layers, resources and textures
// that we can re-use. Destroy the remaining objects before returning.
- qSwap(m_sgObjects, previousSGObjects);
+ qSwap(m_sgObjects, m_previousSGObjects);
// Discard the scene graph nodes from the previous frame.
while (QSGNode *oldChain = firstChild())
delete oldChain;
m_sceneGraphNodes.clear();
nodeHandler.reset(new DelegatedNodeTreeCreator(&m_sceneGraphNodes, apiDelegate));
} else {
- // Save the texture strong refs so they only go out of scope when the method returns and
- // the new vector of texture strong refs has been filled.
- qSwap(m_sgObjects.textureStrongRefs, textureStrongRefs);
+ qSwap(m_sgObjects.bitmapTextures, m_previousSGObjects.bitmapTextures);
+ qSwap(m_sgObjects.mailboxTextures, m_previousSGObjects.mailboxTextures);
nodeHandler.reset(new DelegatedNodeTreeUpdater(&m_sceneGraphNodes));
}
// The RenderPasses list is actually a tree where a parent RenderPass is connected
@@ -906,7 +665,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
if (pass != rootRenderPass) {
QSharedPointer<QSGLayer> rpLayer;
if (buildNewTree) {
- rpLayer = findRenderPassLayer(pass->id, previousSGObjects.renderPassLayers);
+ rpLayer = findRenderPassLayer(pass->id, m_previousSGObjects.renderPassLayers);
if (!rpLayer) {
rpLayer = QSharedPointer<QSGLayer>(apiDelegate->createLayer());
// Avoid any premature texture update since we need to wait
@@ -935,7 +694,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
}
if (scissorRect.IsEmpty()) {
- holdResources(pass, resourceCandidates);
+ holdResources(pass, resourceTracker);
continue;
}
@@ -961,13 +720,13 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
targetRect.Intersect(quadState->clip_rect);
targetRect.Intersect(scissorRect);
if (targetRect.IsEmpty()) {
- holdResources(quad, resourceCandidates);
+ holdResources(quad, resourceTracker);
continue;
}
if (quadState->sorting_context_id != currentSortingContextId) {
flushPolygons(&polygonQueue, renderPassChain,
- nodeHandler.data(), resourceCandidates, apiDelegate);
+ nodeHandler.data(), resourceTracker, apiDelegate);
currentSortingContextId = quadState->sorting_context_id;
}
@@ -989,28 +748,23 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
}
handleQuad(quad, currentLayerChain,
- nodeHandler.data(), resourceCandidates, apiDelegate);
+ nodeHandler.data(), resourceTracker, apiDelegate);
}
flushPolygons(&polygonQueue, renderPassChain,
- nodeHandler.data(), resourceCandidates, apiDelegate);
+ nodeHandler.data(), resourceTracker, apiDelegate);
}
- // Send resources of remaining candidates back to the child compositors so that
- // they can be freed or reused.
- typedef QHash<unsigned, QSharedPointer<ResourceHolder> >::const_iterator
- ResourceHolderIterator;
- ResourceHolderIterator end = resourceCandidates.constEnd();
- for (ResourceHolderIterator it = resourceCandidates.constBegin(); it != end ; ++it)
- resourcesToRelease->push_back((*it)->returnResource());
+ copyMailboxTextures();
m_previousViewportSize = viewportSize;
+ m_previousSGObjects = SGObjects();
}
void DelegatedFrameNode::flushPolygons(
base::circular_deque<std::unique_ptr<viz::DrawPolygon>> *polygonQueue,
QSGNode *renderPassChain,
DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate)
{
if (polygonQueue->empty())
@@ -1030,7 +784,7 @@ void DelegatedFrameNode::flushPolygons(
polygon->TransformToLayerSpace(inverseTransform);
handlePolygon(polygon, currentLayerChain,
- nodeHandler, resourceCandidates, apiDelegate);
+ nodeHandler, resourceTracker, apiDelegate);
};
viz::BspTree(polygonQueue).TraverseWithActionHandler(&actionHandler);
@@ -1040,20 +794,20 @@ void DelegatedFrameNode::handlePolygon(
const viz::DrawPolygon *polygon,
QSGNode *currentLayerChain,
DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate)
{
const viz::DrawQuad *quad = polygon->original_ref();
if (!polygon->is_split()) {
handleQuad(quad, currentLayerChain,
- nodeHandler, resourceCandidates, apiDelegate);
+ nodeHandler, resourceTracker, apiDelegate);
} else {
std::vector<gfx::QuadF> clipRegionList;
polygon->ToQuads2D(&clipRegionList);
for (const auto & clipRegion : clipRegionList)
handleClippedQuad(quad, clipRegion, currentLayerChain,
- nodeHandler, resourceCandidates, apiDelegate);
+ nodeHandler, resourceTracker, apiDelegate);
}
}
@@ -1062,7 +816,7 @@ void DelegatedFrameNode::handleClippedQuad(
const gfx::QuadF &clipRegion,
QSGNode *currentLayerChain,
DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate)
{
if (currentLayerChain) {
@@ -1080,21 +834,21 @@ void DelegatedFrameNode::handleClippedQuad(
currentLayerChain = clipNode;
}
handleQuad(quad, currentLayerChain,
- nodeHandler, resourceCandidates, apiDelegate);
+ nodeHandler, resourceTracker, apiDelegate);
}
void DelegatedFrameNode::handleQuad(
const viz::DrawQuad *quad,
QSGNode *currentLayerChain,
DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate)
{
switch (quad->material) {
case viz::DrawQuad::RENDER_PASS: {
const viz::RenderPassDrawQuad *renderPassQuad = viz::RenderPassDrawQuad::MaterialCast(quad);
if (!renderPassQuad->mask_texture_size.IsEmpty()) {
- ResourceHolder *resource = findAndHoldResource(renderPassQuad->mask_resource_id(), resourceCandidates);
+ const CompositorResource *resource = findAndHoldResource(renderPassQuad->mask_resource_id(), resourceTracker);
Q_UNUSED(resource); // FIXME: QTBUG-67652
}
QSGLayer *layer =
@@ -1107,7 +861,7 @@ void DelegatedFrameNode::handleQuad(
}
case viz::DrawQuad::TEXTURE_CONTENT: {
const viz::TextureDrawQuad *tquad = viz::TextureDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates);
+ const CompositorResource *resource = findAndHoldResource(tquad->resource_id(), resourceTracker);
QSGTexture *texture =
initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate);
QSizeF textureSize;
@@ -1158,7 +912,7 @@ void DelegatedFrameNode::handleQuad(
}
case viz::DrawQuad::TILED_CONTENT: {
const viz::TileDrawQuad *tquad = viz::TileDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates);
+ const CompositorResource *resource = findAndHoldResource(tquad->resource_id(), resourceTracker);
nodeHandler->setupTextureContentNode(
initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate),
toQt(quad->rect), toQt(tquad->tex_coord_rect),
@@ -1168,17 +922,17 @@ void DelegatedFrameNode::handleQuad(
}
case viz::DrawQuad::YUV_VIDEO_CONTENT: {
const viz::YUVVideoDrawQuad *vquad = viz::YUVVideoDrawQuad::MaterialCast(quad);
- ResourceHolder *yResource =
- findAndHoldResource(vquad->y_plane_resource_id(), resourceCandidates);
- ResourceHolder *uResource =
- findAndHoldResource(vquad->u_plane_resource_id(), resourceCandidates);
- ResourceHolder *vResource =
- findAndHoldResource(vquad->v_plane_resource_id(), resourceCandidates);
- ResourceHolder *aResource = 0;
+ const CompositorResource *yResource =
+ findAndHoldResource(vquad->y_plane_resource_id(), resourceTracker);
+ const CompositorResource *uResource =
+ findAndHoldResource(vquad->u_plane_resource_id(), resourceTracker);
+ const CompositorResource *vResource =
+ findAndHoldResource(vquad->v_plane_resource_id(), resourceTracker);
+ const CompositorResource *aResource = nullptr;
// This currently requires --enable-vp8-alpha-playback and
// needs a video with alpha data to be triggered.
if (vquad->a_plane_resource_id())
- aResource = findAndHoldResource(vquad->a_plane_resource_id(), resourceCandidates);
+ aResource = findAndHoldResource(vquad->a_plane_resource_id(), resourceTracker);
nodeHandler->setupYUVVideoNode(
initAndHoldTexture(yResource, quad->ShouldDrawWithBlending()),
@@ -1194,14 +948,13 @@ void DelegatedFrameNode::handleQuad(
}
case viz::DrawQuad::STREAM_VIDEO_CONTENT: {
const viz::StreamVideoDrawQuad *squad = viz::StreamVideoDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(squad->resource_id(), resourceCandidates);
+ const CompositorResource *resource = findAndHoldResource(squad->resource_id(), resourceTracker);
MailboxTexture *texture = static_cast<MailboxTexture *>(
- initAndHoldTexture(resource, quad->ShouldDrawWithBlending()));
- // since this is not default TEXTURE_2D type
- texture->setTarget(GL_TEXTURE_EXTERNAL_OES);
+ initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate, GL_TEXTURE_EXTERNAL_OES));
- nodeHandler->setupStreamVideoNode(texture, toQt(squad->rect), toQt(squad->matrix.matrix()),
- currentLayerChain);
+ QMatrix4x4 qMatrix;
+ convertToQt(squad->matrix.matrix(), qMatrix);
+ nodeHandler->setupStreamVideoNode(texture, toQt(squad->rect), qMatrix, currentLayerChain);
break;
#endif // GL_OES_EGL_image_external
#endif // QT_NO_OPENGL
@@ -1213,75 +966,100 @@ void DelegatedFrameNode::handleQuad(
}
}
-ResourceHolder *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates)
+const CompositorResource *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, const CompositorResourceTracker *resourceTracker)
{
- // ResourceHolders must survive when the scene graph destroys our node branch
- QSharedPointer<ResourceHolder> &resource = m_chromiumCompositorData->resourceHolders[resourceId];
- if (!resource)
- resource = candidates.take(resourceId);
- Q_ASSERT(resource);
- return resource.data();
+ return resourceTracker->findResource(resourceId);
}
-void DelegatedFrameNode::holdResources(const viz::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates)
+void DelegatedFrameNode::holdResources(const viz::DrawQuad *quad, const CompositorResourceTracker *resourceTracker)
{
for (auto resource : quad->resources)
- findAndHoldResource(resource, candidates);
+ findAndHoldResource(resource, resourceTracker);
}
-void DelegatedFrameNode::holdResources(const viz::RenderPass *pass, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates)
+void DelegatedFrameNode::holdResources(const viz::RenderPass *pass, const CompositorResourceTracker *resourceTracker)
{
for (const auto &quad : pass->quad_list)
- holdResources(quad, candidates);
+ holdResources(quad, resourceTracker);
}
-QSGTexture *DelegatedFrameNode::initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate)
+template<class Container, class Key>
+inline auto &findTexture(Container &map, Container &previousMap, const Key &key)
{
- // QSGTextures must be destroyed in the scene graph thread as part of the QSGNode tree,
- // so we can't store them with the ResourceHolder in m_chromiumCompositorData.
- // Hold them through a QSharedPointer solely on the root DelegatedFrameNode of the web view
- // and access them through a QWeakPointer from the resource holder to find them later.
- m_sgObjects.textureStrongRefs.append(resource->initTexture(quadIsAllOpaque, apiDelegate));
- return m_sgObjects.textureStrongRefs.last().data();
+ auto &value = map[key];
+ if (value)
+ return value;
+ value = previousMap[key];
+ return value;
}
-void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxesToFetch)
+QSGTexture *DelegatedFrameNode::initAndHoldTexture(const CompositorResource *resource, bool hasAlphaChannel, RenderWidgetHostViewQtDelegate *apiDelegate, int target)
{
-#ifndef QT_NO_OPENGL
- QList<gl::TransferableFence> transferredFences;
- {
- QMutexLocker lock(&m_mutex);
- QVector<MailboxTexture *> mailboxesToPull;
- mailboxesToPull.reserve(mailboxesToFetch.size());
-
- gpu::SyncPointManager *syncPointManager = sync_point_manager();
- scoped_refptr<base::SingleThreadTaskRunner> gpuTaskRunner = gpu_task_runner();
- Q_ASSERT(m_numPendingSyncPoints == 0);
- m_numPendingSyncPoints = mailboxesToFetch.count();
- for (MailboxTexture *mailboxTexture : qAsConst(mailboxesToFetch)) {
- gpu::SyncToken &syncToken = mailboxTexture->mailboxHolder().sync_token;
- const auto task = base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture);
- if (!syncPointManager->WaitOutOfOrder(syncToken, std::move(task)))
- mailboxesToPull.append(mailboxTexture);
- }
- if (!mailboxesToPull.isEmpty()) {
- auto task = base::BindOnce(&DelegatedFrameNode::pullTextures, this, std::move(mailboxesToPull));
- gpuTaskRunner->PostTask(FROM_HERE, std::move(task));
- }
-
- m_mailboxesFetchedWaitCond.wait(&m_mutex);
- m_textureFences.swap(transferredFences);
+ QSGTexture::Filtering filtering;
+
+ if (resource->filter == GL_NEAREST)
+ filtering = QSGTexture::Nearest;
+ else if (resource->filter == GL_LINEAR)
+ filtering = QSGTexture::Linear;
+ else {
+ // Depends on qtdeclarative fix, see QTBUG-71322
+#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 1)
+ filtering = QSGTexture::Linear;
+#else
+ filtering = QSGTexture::Nearest;
+#endif
}
- for (gl::TransferableFence sync : qAsConst(transferredFences)) {
- // We need to wait on the fences on the Qt current context, and
- // can therefore not use GLFence routines that uses a different
- // concept of current context.
- waitChromiumSync(&sync);
- deleteChromiumSync(&sync);
+ if (resource->is_software) {
+ QSharedPointer<QSGTexture> &texture =
+ findTexture(m_sgObjects.bitmapTextures, m_previousSGObjects.bitmapTextures, resource->id);
+ if (texture)
+ return texture.data();
+ texture = createBitmapTexture(resource, hasAlphaChannel, apiDelegate);
+ texture->setFiltering(filtering);
+ return texture.data();
+ } else {
+ QSharedPointer<MailboxTexture> &texture =
+ findTexture(m_sgObjects.mailboxTextures, m_previousSGObjects.mailboxTextures, resource->id);
+ if (texture)
+ return texture.data();
+ texture = createMailboxTexture(resource, hasAlphaChannel, target);
+ texture->setFiltering(filtering);
+ return texture.data();
}
+}
-#if defined(USE_OZONE) && !defined(QT_NO_OPENGL)
+QSharedPointer<QSGTexture> DelegatedFrameNode::createBitmapTexture(const CompositorResource *resource, bool hasAlphaChannel, RenderWidgetHostViewQtDelegate *apiDelegate)
+{
+ Q_ASSERT(apiDelegate);
+ viz::SharedBitmap *sharedBitmap = resource->bitmap.get();
+ gfx::Size size = resource->size;
+
+ // QSG interprets QImage::hasAlphaChannel meaning that a node should enable blending
+ // to draw it but Chromium keeps this information in the quads.
+ // The input format is currently always Format_ARGB32_Premultiplied, so assume that all
+ // alpha bytes are 0xff if quads aren't requesting blending and avoid the conversion
+ // from Format_ARGB32_Premultiplied to Format_RGB32 just to get hasAlphaChannel to
+ // return false.
+ QImage::Format format = hasAlphaChannel ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
+ QImage image = sharedBitmap
+ ? QImage(sharedBitmap->pixels(), size.width(), size.height(), format)
+ : QImage(size.width(), size.height(), format);
+ return QSharedPointer<QSGTexture>(apiDelegate->createTextureFromImage(image.copy()));
+}
+
+QSharedPointer<MailboxTexture> DelegatedFrameNode::createMailboxTexture(const CompositorResource *resource, bool hasAlphaChannel, int target)
+{
+#ifndef QT_NO_OPENGL
+ return QSharedPointer<MailboxTexture>::create(resource, hasAlphaChannel, target);
+#else
+ Q_UNREACHABLE();
+#endif
+}
+
+void DelegatedFrameNode::copyMailboxTextures()
+{
+#if !defined(QT_NO_OPENGL) && defined(USE_OZONE)
// Workaround when context is not shared QTBUG-48969
// Make slow copy between two contexts.
if (!m_contextShared) {
@@ -1296,13 +1074,17 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe
GLuint fbo = 0;
funcs->glGenFramebuffers(1, &fbo);
- for (MailboxTexture *mailboxTexture : qAsConst(mailboxesToFetch)) {
+ for (const QSharedPointer<MailboxTexture> &mailboxTexture : qAsConst(m_sgObjects.mailboxTextures)) {
+ if (mailboxTexture->m_ownsTexture)
+ continue;
+
// Read texture into QImage from shared context.
// Switch to shared context.
sharedContext->makeCurrent(m_offsurface.data());
funcs = sharedContext->functions();
QImage img(mailboxTexture->textureSize(), QImage::Format_RGBA8888_Premultiplied);
funcs->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ mailboxTexture->m_fence->wait();
funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mailboxTexture->m_textureId, 0);
GLenum status = funcs->glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
@@ -1336,69 +1118,6 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe
currentContext->makeCurrent(surface);
}
#endif
-#else
- Q_UNUSED(mailboxesToFetch)
-#endif //QT_NO_OPENGL
-}
-
-
-void DelegatedFrameNode::pullTextures(DelegatedFrameNode *frameNode, const QVector<MailboxTexture *> textures)
-{
-#ifndef QT_NO_OPENGL
- gpu::MailboxManager *mailboxManager = mailbox_manager();
- for (MailboxTexture *texture : textures) {
- gpu::SyncToken &syncToken = texture->mailboxHolder().sync_token;
- if (syncToken.HasData())
- mailboxManager->PullTextureUpdates(syncToken);
- texture->fetchTexture(mailboxManager);
- --frameNode->m_numPendingSyncPoints;
- }
-
- fenceAndUnlockQt(frameNode);
-#else
- Q_UNUSED(frameNode)
- Q_UNUSED(textures)
-#endif
-}
-
-void DelegatedFrameNode::pullTexture(DelegatedFrameNode *frameNode, MailboxTexture *texture)
-{
-#ifndef QT_NO_OPENGL
- gpu::MailboxManager *mailboxManager = mailbox_manager();
- gpu::SyncToken &syncToken = texture->mailboxHolder().sync_token;
- if (syncToken.HasData())
- mailboxManager->PullTextureUpdates(syncToken);
- texture->fetchTexture(mailboxManager);
- --frameNode->m_numPendingSyncPoints;
-
- fenceAndUnlockQt(frameNode);
-#else
- Q_UNUSED(frameNode)
- Q_UNUSED(texture)
-#endif
-}
-
-void DelegatedFrameNode::fenceAndUnlockQt(DelegatedFrameNode *frameNode)
-{
-#ifndef QT_NO_OPENGL
- if (!!gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) {
- // Create a fence on the Chromium GPU-thread and context
- std::unique_ptr<gl::GLFence> fence = gl::GLFence::Create();
- // But transfer it to something generic since we need to read it using Qt's OpenGL.
- frameNode->m_textureFences.append(fence->Transfer());
- }
- if (frameNode->m_numPendingSyncPoints == 0)
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::unlockQt, frameNode));
-#else
- Q_UNUSED(frameNode)
-#endif
-}
-
-void DelegatedFrameNode::unlockQt(DelegatedFrameNode *frameNode)
-{
- QMutexLocker lock(&frameNode->m_mutex);
- // Signal preprocess() the textures are ready
- frameNode->m_mailboxesFetchedWaitCond.wakeOne();
}
} // namespace QtWebEngineCore
diff --git a/src/core/delegated_frame_node.h b/src/core/compositor/delegated_frame_node.h
index e37ad08a3..34e4ba029 100644
--- a/src/core/delegated_frame_node.h
+++ b/src/core/compositor/delegated_frame_node.h
@@ -43,15 +43,10 @@
#include "base/containers/circular_deque.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/render_pass.h"
-#include "components/viz/common/resources/transferable_resource.h"
-#include "gpu/command_buffer/service/sync_point_manager.h"
-#include "ui/gl/gl_fence.h"
-#include <QMutex>
-#include <QSGNode>
-#include <QSharedData>
-#include <QSharedPointer>
-#include <QWaitCondition>
+
+#include <QtCore/QSharedPointer>
#include <QtGui/QOffscreenSurface>
+#include <QtQuick/QSGTransformNode>
#include "chromium_gpu_helper.h"
#include "render_widget_host_view_qt_delegate.h"
@@ -72,77 +67,60 @@ class DrawPolygon;
namespace QtWebEngineCore {
+class CompositorResource;
+class CompositorResourceTracker;
class DelegatedNodeTreeHandler;
class MailboxTexture;
-class ResourceHolder;
-
-// Separating this data allows another DelegatedFrameNode to reconstruct the QSGNode tree from the mailbox textures
-// and render pass information.
-class ChromiumCompositorData : public QSharedData {
-public:
- ChromiumCompositorData() : frameDevicePixelRatio(1) { }
- QHash<unsigned, QSharedPointer<ResourceHolder> > resourceHolders;
- viz::CompositorFrame frameData;
- viz::CompositorFrame previousFrameData;
- qreal frameDevicePixelRatio;
-};
class DelegatedFrameNode : public QSGTransformNode {
public:
DelegatedFrameNode();
~DelegatedFrameNode();
- void preprocess();
- void commit(ChromiumCompositorData *chromiumCompositorData, std::vector<viz::ReturnedResource> *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate);
+ void preprocess() override;
+ void commit(const viz::CompositorFrame &pendingFrame, const viz::CompositorFrame &committedFrame, const CompositorResourceTracker *resourceTracker, RenderWidgetHostViewQtDelegate *apiDelegate);
private:
void flushPolygons(base::circular_deque<std::unique_ptr<viz::DrawPolygon> > *polygonQueue,
QSGNode *renderPassChain,
DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate);
void handlePolygon(
const viz::DrawPolygon *polygon,
QSGNode *currentLayerChain,
DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate);
void handleClippedQuad(
const viz::DrawQuad *quad,
const gfx::QuadF &clipRegion,
QSGNode *currentLayerChain,
DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate);
void handleQuad(
const viz::DrawQuad *quad,
QSGNode *currentLayerChain,
DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ const CompositorResourceTracker *resourceTracker,
RenderWidgetHostViewQtDelegate *apiDelegate);
- void fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxesToFetch);
- // Making those callbacks static bypasses base::Bind's ref-counting requirement
- // of the this pointer when the callback is a method.
- static void pullTexture(DelegatedFrameNode *frameNode, MailboxTexture *mailbox);
- static void pullTextures(DelegatedFrameNode *frameNode, const QVector<MailboxTexture *> mailboxes);
- static void fenceAndUnlockQt(DelegatedFrameNode *frameNode);
- static void unlockQt(DelegatedFrameNode *frameNode);
-
- ResourceHolder *findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates);
- void holdResources(const viz::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates);
- void holdResources(const viz::RenderPass *pass, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates);
- QSGTexture *initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0);
-
- QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData;
+
+ const CompositorResource *findAndHoldResource(unsigned resourceId, const CompositorResourceTracker *resourceTracker);
+ void holdResources(const viz::DrawQuad *quad, const CompositorResourceTracker *resourceTracker);
+ void holdResources(const viz::RenderPass *pass, const CompositorResourceTracker *resourceTracker);
+ QSGTexture *initAndHoldTexture(const CompositorResource *resource, bool hasAlphaChannel, RenderWidgetHostViewQtDelegate *apiDelegate = 0, int target = -1);
+ QSharedPointer<QSGTexture> createBitmapTexture(const CompositorResource *resource, bool hasAlphaChannel, RenderWidgetHostViewQtDelegate *apiDelegate);
+ QSharedPointer<MailboxTexture> createMailboxTexture(const CompositorResource *resource, bool hasAlphaChannel, int target);
+
+ void copyMailboxTextures();
+
struct SGObjects {
QVector<QPair<int, QSharedPointer<QSGLayer> > > renderPassLayers;
QVector<QSharedPointer<QSGRootNode> > renderPassRootNodes;
- QVector<QSharedPointer<QSGTexture> > textureStrongRefs;
- } m_sgObjects;
+ QHash<unsigned, QSharedPointer<QSGTexture> > bitmapTextures;
+ QHash<unsigned, QSharedPointer<MailboxTexture> > mailboxTextures;
+ } m_sgObjects, m_previousSGObjects;
QVector<QSGNode*> m_sceneGraphNodes;
- int m_numPendingSyncPoints;
- QWaitCondition m_mailboxesFetchedWaitCond;
- QMutex m_mutex;
- QList<gl::TransferableFence> m_textureFences;
#if defined(USE_OZONE)
bool m_contextShared;
QScopedPointer<QOffscreenSurface> m_offsurface;
diff --git a/src/core/stream_video_node.cpp b/src/core/compositor/stream_video_node.cpp
index 29922f866..29922f866 100644
--- a/src/core/stream_video_node.cpp
+++ b/src/core/compositor/stream_video_node.cpp
diff --git a/src/core/stream_video_node.h b/src/core/compositor/stream_video_node.h
index 9d937791f..9d937791f 100644
--- a/src/core/stream_video_node.h
+++ b/src/core/compositor/stream_video_node.h
diff --git a/src/core/yuv_video_node.cpp b/src/core/compositor/yuv_video_node.cpp
index 4a436d952..4a436d952 100644
--- a/src/core/yuv_video_node.cpp
+++ b/src/core/compositor/yuv_video_node.cpp
diff --git a/src/core/yuv_video_node.h b/src/core/compositor/yuv_video_node.h
index dca8fa5e2..dca8fa5e2 100644
--- a/src/core/yuv_video_node.h
+++ b/src/core/compositor/yuv_video_node.h
diff --git a/src/core/config/common.pri b/src/core/config/common.pri
index ddb4ca4bf..be57942d2 100644
--- a/src/core/config/common.pri
+++ b/src/core/config/common.pri
@@ -4,6 +4,7 @@ QT_FOR_CONFIG += webenginecore
gn_args += \
use_qt=true \
+ closure_compile=false \
is_component_build=false \
is_shared=true \
enable_message_center=false \
@@ -11,15 +12,17 @@ gn_args += \
enable_nacl=false \
enable_remoting=false \
enable_reporting=false \
+ enable_swiftshader=false \
+ enable_web_auth=false \
enable_web_speech=false \
enable_widevine=true \
has_native_accessibility=false \
use_allocator_shim=false \
use_allocator=\"none\" \
+ use_custom_libcxx=false \
v8_use_external_startup_data=false \
- treat_warnings_as_errors=false \
- enable_swiftshader=false \
- use_custom_libcxx=false
+ toolkit_views=false \
+ treat_warnings_as_errors=false
!win32: gn_args += \
use_jumbo_build=true \
diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri
index 4426901cf..e49df90e7 100644
--- a/src/core/config/mac_osx.pri
+++ b/src/core/config/mac_osx.pri
@@ -28,8 +28,6 @@ gn_args += \
clang_use_chrome_plugins=false \
mac_deployment_target=\"$${QMAKE_MACOSX_DEPLOYMENT_TARGET}\" \
mac_sdk_min=\"$${QMAKE_MAC_SDK_VERSION}\" \
- mac_views_browser=false \
- toolkit_views=false \
use_external_popup_menu=false
qtConfig(webengine-spellchecker) {
diff --git a/src/core/configure.json b/src/core/configure.json
index 044d85527..755a525a8 100644
--- a/src/core/configure.json
+++ b/src/core/configure.json
@@ -25,6 +25,8 @@
"webengine-v8-snapshot": "boolean",
"webengine-webchannel": "boolean",
"webengine-kerberos": "boolean",
+ "webengine-widgets": "boolean",
+ "webengine-qml": "boolean",
"alsa": { "type": "boolean", "name": "webengine-alsa" },
"pulseaudio": { "type": "boolean", "name": "webengine-pulseaudio" },
"ffmpeg": { "type": "enum", "name": "webengine-system-ffmpeg", "values": { "system": "yes", "qt": "no" } },
@@ -82,9 +84,9 @@
]
},
"webengine-harfbuzz": {
- "label": "harfbuzz >= 1.4.2",
+ "label": "harfbuzz >= 2.0.0",
"sources": [
- { "type": "pkgConfig", "args": "harfbuzz >= 1.4.2" }
+ { "type": "pkgConfig", "args": "harfbuzz >= 2.0.0" }
]
},
"webengine-glib": {
@@ -546,15 +548,6 @@
"condition": "config.macos && features.webengine-spellchecker",
"output": [ "publicFeature" ]
},
- "webengine-ui-delegates": {
- "label": "UI Delegates",
- "output": [ "privateFeature" ]
- },
- "webengine-testsupport": {
- "label": "Test Support",
- "autoDetect": "features.private_tests || call.isTestsInBuildParts",
- "output": [ "privateFeature" ]
- },
"webengine-webrtc": {
"label": "WebRTC",
"purpose": "Provides WebRTC support.",
@@ -657,6 +650,19 @@
"label": "Thumb instruction set",
"condition": "config.linux && features.webengine-embedded-build && arch.arm && tests.webengine-arm-thumb",
"output": [ "privateFeature" ]
+ },
+ "webengine-widgets": {
+ "label": "Qt WebEngine Widgets",
+ "purpose": "Provides WebEngine Widgets support.",
+ "section": "WebEngine",
+ "condition": "module.widgets",
+ "output": [ "privateFeature" ]
+ },
+ "webengine-qml": {
+ "label": "Qt WebEngine Qml",
+ "purpose": "Provides WebEngine Qml support.",
+ "section": "WebEngine",
+ "output": [ "privateFeature" ]
}
},
@@ -705,8 +711,10 @@
"summary": [
{
- "section": "Qt WebEngine",
+ "section": "Qt WebEngineCore",
"entries": [
+ "webengine-widgets",
+ "webengine-qml",
"webengine-embedded-build",
"webengine-pepper-plugins",
"webengine-printing-and-pdf",
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index 0a51cc261..98262570c 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -42,12 +42,16 @@
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/message_loop/message_loop.h"
+#include "base/task/post_task.h"
+#include "base/threading/thread_restrictions.h"
#if QT_CONFIG(webengine_spellchecker)
#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
#endif
#include "components/network_hints/browser/network_hints_message_filter.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/common/url_schemes.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/client_certificate_delegate.h"
@@ -85,6 +89,7 @@
#include "qtwebengine/grit/qt_webengine_resources.h"
+#include "client_cert_override_p.h"
#include "profile_adapter.h"
#include "browser_main_parts_qt.h"
#include "browser_message_filter_qt.h"
@@ -95,7 +100,6 @@
#include "login_delegate_qt.h"
#include "media_capture_devices_dispatcher.h"
#include "net/network_delegate_qt.h"
-#include "net/qrc_protocol_handler_qt.h"
#include "net/url_request_context_getter_qt.h"
#if QT_CONFIG(webengine_printing_and_pdf)
#include "printing/printing_message_filter_qt.h"
@@ -114,18 +118,6 @@
#include "ui/base/resource/resource_bundle.h"
#endif
-#if defined(USE_NSS_CERTS)
-#include "net/ssl/client_cert_store_nss.h"
-#endif
-
-#if defined(OS_WIN)
-#include "net/ssl/client_cert_store_win.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "net/ssl/client_cert_store_mac.h"
-#endif
-
#if QT_CONFIG(webengine_pepper_plugins)
#include "content/public/browser/browser_ppapi_host.h"
#include "ppapi/host/ppapi_host.h"
@@ -248,10 +240,10 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost*
{
const int id = host->GetID();
Profile *profile = Profile::FromBrowserContext(host->GetBrowserContext());
- content::BrowserThread::PostTaskAndReplyWithResult(
- content::BrowserThread::IO, FROM_HERE,
- base::Bind(&net::URLRequestContextGetter::GetURLRequestContext, base::Unretained(profile->GetRequestContext())),
- base::Bind(&ContentBrowserClientQt::AddNetworkHintsMessageFilter, base::Unretained(this), id));
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&net::URLRequestContextGetter::GetURLRequestContext, base::Unretained(profile->GetRequestContext())),
+ base::BindOnce(&ContentBrowserClientQt::AddNetworkHintsMessageFilter, base::Unretained(this), id));
// FIXME: Add a settings variable to enable/disable the file scheme.
content::ChildProcessSecurityPolicy::GetInstance()->GrantRequestScheme(id, url::kFileScheme);
@@ -382,17 +374,8 @@ std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertSt
{
if (!resource_context)
return nullptr;
-#if defined(USE_NSS_CERTS)
- // FIXME: Give it a proper callback for a password delegate.
- return std::unique_ptr<net::ClientCertStore>(
- new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory()));
-#elif defined(OS_WIN)
- return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
-#elif defined(OS_MACOSX)
- return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
-#else
- return nullptr;
-#endif
+
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertOverrideStore());
}
std::string ContentBrowserClientQt::GetApplicationLocale()
@@ -618,11 +601,18 @@ void ContentBrowserClientQt::AddNetworkHintsMessageFilter(int render_process_id,
if (!host)
return;
- content::BrowserMessageFilter *network_hints_message_filter(
- new network_hints::NetworkHintsMessageFilter(context->host_resolver()));
+ content::BrowserMessageFilter *network_hints_message_filter =
+ new network_hints::NetworkHintsMessageFilter(render_process_id);
host->AddFilter(network_hints_message_filter);
}
+bool ContentBrowserClientQt::ShouldEnableStrictSiteIsolation()
+{
+ // mirroring AwContentBrowserClient, CastContentBrowserClient and
+ // HeadlessContentBrowserClient
+ return false;
+}
+
bool ContentBrowserClientQt::AllowGetCookie(const GURL &url,
const GURL &first_party,
const net::CookieList & /*cookie_list*/,
@@ -671,7 +661,7 @@ bool ContentBrowserClientQt::AllowServiceWorker(const GURL &scope,
// We control worker access to FS and indexed-db using cookie permissions, this is mirroring Chromium's logic.
void ContentBrowserClientQt::AllowWorkerFileSystem(const GURL &url,
content::ResourceContext *context,
- const std::vector<std::pair<int, int> > &/*render_frames*/,
+ const std::vector<content::GlobalFrameRoutingId> &/*render_frames*/,
base::Callback<void(bool)> callback)
{
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -682,7 +672,7 @@ void ContentBrowserClientQt::AllowWorkerFileSystem(const GURL &url,
bool ContentBrowserClientQt::AllowWorkerIndexedDB(const GURL &url,
const base::string16 &/*name*/,
content::ResourceContext *context,
- const std::vector<std::pair<int, int> > &/*render_frames*/)
+ const std::vector<content::GlobalFrameRoutingId> &/*render_frames*/)
{
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
NetworkDelegateQt *networkDelegate = static_cast<NetworkDelegateQt *>(context->GetRequestContext()->network_delegate());
@@ -715,15 +705,13 @@ bool ContentBrowserClientQt::HandleExternalProtocol(
Q_UNUSED(child_id);
Q_UNUSED(navigation_data);
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
- FROM_HERE,
- base::BindOnce(&LaunchURL,
- url,
- web_contents_getter,
- page_transition,
- is_main_frame,
- has_user_gesture));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&LaunchURL,
+ url,
+ web_contents_getter,
+ page_transition,
+ is_main_frame,
+ has_user_gesture));
return true;
}
@@ -737,9 +725,9 @@ scoped_refptr<content::LoginDelegate> ContentBrowserClientQt::CreateLoginDelegat
bool first_auth_attempt,
LoginAuthRequiredCallback auth_required_callback)
{
- return base::MakeRefCounted<LoginDelegateQt>(authInfo, web_contents_getter, url, first_auth_attempt, std::move(auth_required_callback));
+ auto loginDelegate = base::MakeRefCounted<LoginDelegateQt>(authInfo, web_contents_getter, url, first_auth_attempt, std::move(auth_required_callback));
+ loginDelegate->triggerDialog();
+ return loginDelegate;
}
} // namespace QtWebEngineCore
-
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(QtWebEngineCore::ServiceDriver);
diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h
index b2761b311..9e503cace 100644
--- a/src/core/content_browser_client_qt.h
+++ b/src/core/content_browser_client_qt.h
@@ -135,6 +135,7 @@ public:
bool user_gesture,
bool opener_suppressed,
bool* no_javascript_access) override;
+ bool ShouldEnableStrictSiteIsolation() override;
bool AllowGetCookie(const GURL& url,
const GURL& first_party,
@@ -161,13 +162,13 @@ public:
void AllowWorkerFileSystem(const GURL &url,
content::ResourceContext *context,
- const std::vector<std::pair<int, int> > &render_frames,
+ const std::vector<content::GlobalFrameRoutingId> &render_frames,
base::Callback<void(bool)> callback) override;
bool AllowWorkerIndexedDB(const GURL &url,
const base::string16 &name,
content::ResourceContext *context,
- const std::vector<std::pair<int, int> > &render_frames) override;
+ const std::vector<content::GlobalFrameRoutingId> &render_frames) override;
#if QT_CONFIG(webengine_geolocation)
std::unique_ptr<device::LocationProvider> OverrideSystemLocationProvider() override;
diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp
index 1a3be31be..41e3f7f6c 100644
--- a/src/core/content_client_qt.cpp
+++ b/src/core/content_client_qt.cpp
@@ -56,7 +56,6 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
-#include "net/qrc_protocol_handler_qt.h"
#include "type_conversion.h"
#include <QCoreApplication>
@@ -391,6 +390,11 @@ base::RefCountedMemory *ContentClientQt::GetDataResourceBytes(int resource_id) c
return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(resource_id);
}
+gfx::Image &ContentClientQt::GetNativeImageNamed(int resource_id) const
+{
+ return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
+}
+
base::string16 ContentClientQt::GetLocalizedString(int message_id) const
{
return l10n_util::GetStringUTF16(message_id);
diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h
index fbafa6a4b..c3feded00 100644
--- a/src/core/content_client_qt.h
+++ b/src/core/content_client_qt.h
@@ -58,7 +58,8 @@ public:
std::vector<media::CdmHostFilePath> *cdm_host_file_paths) override;
base::StringPiece GetDataResource(int, ui::ScaleFactor) const override;
- base::RefCountedMemory* GetDataResourceBytes(int resource_id) const override;
+ base::RefCountedMemory* GetDataResourceBytes(int resource_id) const override;
+ gfx::Image &GetNativeImageNamed(int resource_id) const override;
std::string GetUserAgent() const override { return getUserAgent(); }
base::string16 GetLocalizedString(int message_id) const override;
std::string GetProduct() const override;
diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp
index 2811d5545..dc32bb8c1 100644
--- a/src/core/content_main_delegate_qt.cpp
+++ b/src/core/content_main_delegate_qt.cpp
@@ -40,17 +40,18 @@
#include "content_main_delegate_qt.h"
#include "base/command_line.h"
-#include <base/i18n/rtl.h>
+#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
-#include <chrome/grit/generated_resources.h>
+#include "chrome/grit/generated_resources.h"
+#include "content/public/browser/browser_main_runner.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/resource/resource_bundle.h"
-#include <ui/base/webui/jstemplate_builder.h>
+#include "ui/base/webui/jstemplate_builder.h"
#include "net/grit/net_resources.h"
#include "net/base/net_module.h"
#include "services/service_manager/sandbox/switches.h"
@@ -59,6 +60,7 @@
#include "content_client_qt.h"
#include "renderer/content_renderer_client_qt.h"
#include "type_conversion.h"
+#include "web_engine_context.h"
#include "web_engine_library_info.h"
#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
@@ -71,6 +73,10 @@
#include <QtCore/qcoreapplication.h>
+namespace content {
+ContentClient *GetContentClient();
+}
+
namespace QtWebEngineCore {
// The logic of this function is based on chrome/common/net/net_resource_provider.cc
@@ -167,6 +173,12 @@ content::ContentBrowserClient *ContentMainDelegateQt::CreateContentBrowserClient
return m_browserClient.get();
}
+content::ContentGpuClient *ContentMainDelegateQt::CreateContentGpuClient()
+{
+ m_gpuClient.reset(new ContentGpuClientQt);
+ return m_gpuClient.get();
+}
+
content::ContentRendererClient *ContentMainDelegateQt::CreateContentRendererClient()
{
#if defined(OS_LINUX)
@@ -221,7 +233,8 @@ bool ContentMainDelegateQt::BasicStartupComplete(int *exit_code)
#if QT_CONFIG(webengine_spellchecker)
SafeOverridePath(base::DIR_APP_DICTIONARIES, WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES));
#endif
- SetContentClient(new ContentClientQt);
+ if (!content::GetContentClient())
+ content::SetContentClient(new ContentClientQt);
url::CustomScheme::LoadSchemes(base::CommandLine::ForCurrentProcess());
diff --git a/src/core/content_main_delegate_qt.h b/src/core/content_main_delegate_qt.h
index c06afb0fb..4d2f33792 100644
--- a/src/core/content_main_delegate_qt.h
+++ b/src/core/content_main_delegate_qt.h
@@ -42,6 +42,7 @@
#include "content/public/app/content_main_delegate.h"
+#include "compositor/content_gpu_client_qt.h"
#include "content_browser_client_qt.h"
#include "content_utility_client_qt.h"
@@ -56,12 +57,14 @@ public:
void PreSandboxStartup() override;
content::ContentBrowserClient* CreateContentBrowserClient() override;
+ content::ContentGpuClient* CreateContentGpuClient() override;
content::ContentRendererClient* CreateContentRendererClient() override;
content::ContentUtilityClient* CreateContentUtilityClient() override;
bool BasicStartupComplete(int* /*exit_code*/) override;
private:
std::unique_ptr<ContentBrowserClientQt> m_browserClient;
+ std::unique_ptr<ContentGpuClientQt> m_gpuClient;
std::unique_ptr<ContentUtilityClientQt> m_utilityClient;
};
diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri
index e92dd60ff..3918dc0aa 100644
--- a/src/core/core_chromium.pri
+++ b/src/core/core_chromium.pri
@@ -38,6 +38,7 @@ qtConfig(egl): CONFIG += egl
INCLUDEPATH += $$PWD $$PWD/api
SOURCES = \
+ accessibility_activation_observer.cpp \
accessibility_tree_formatter_qt.cpp \
authentication_dialog_controller.cpp \
browser_accessibility_manager_qt.cpp \
@@ -46,8 +47,8 @@ SOURCES = \
browser_main_parts_qt.cpp \
browser_message_filter_qt.cpp \
certificate_error_controller.cpp \
- chromium_gpu_helper.cpp \
chromium_overrides.cpp \
+ client_cert_override_key.cpp \
client_cert_select_controller.cpp \
clipboard_qt.cpp \
color_chooser_qt.cpp \
@@ -55,12 +56,15 @@ SOURCES = \
common/qt_ipc_logging.cpp \
common/qt_messages.cpp \
common/user_script_data.cpp \
- compositor.cpp \
+ compositor/chromium_gpu_helper.cpp \
+ compositor/compositor.cpp \
+ compositor/compositor_resource_tracker.cpp \
+ compositor/content_gpu_client_qt.cpp \
+ compositor/delegated_frame_node.cpp \
content_client_qt.cpp \
content_browser_client_qt.cpp \
content_main_delegate_qt.cpp \
content_utility_client_qt.cpp \
- delegated_frame_node.cpp \
desktop_screen_qt.cpp \
devtools_frontend_qt.cpp \
devtools_manager_delegate_qt.cpp \
@@ -76,13 +80,12 @@ SOURCES = \
net/custom_protocol_handler.cpp \
net/network_delegate_qt.cpp \
net/proxy_config_service_qt.cpp \
- net/qrc_protocol_handler_qt.cpp \
+ net/qrc_url_scheme_handler.cpp \
net/ssl_host_state_delegate_qt.cpp \
net/url_request_context_getter_qt.cpp \
net/url_request_custom_job.cpp \
net/url_request_custom_job_delegate.cpp \
net/url_request_custom_job_proxy.cpp \
- net/url_request_qrc_job_qt.cpp \
net/webui_controller_factory_qt.cpp \
ozone/gl_context_qt.cpp \
ozone/gl_ozone_egl_qt.cpp \
@@ -100,6 +103,7 @@ SOURCES = \
profile_io_data_qt.cpp \
quota_permission_context_qt.cpp \
quota_request_controller_impl.cpp \
+ qwebengineclientcertificatestore.cpp \
register_protocol_handler_request_controller_impl.cpp \
render_view_context_menu_qt.cpp \
render_view_observer_host_qt.cpp \
@@ -113,6 +117,9 @@ SOURCES = \
resource_bundle_qt.cpp \
resource_context_qt.cpp \
service/service_qt.cpp \
+ touch_handle_drawable_qt.cpp \
+ touch_selection_controller_client_qt.cpp \
+ touch_selection_menu_controller.cpp \
type_conversion.cpp \
user_script.cpp \
visited_links_manager_qt.cpp \
@@ -120,12 +127,14 @@ SOURCES = \
web_contents_delegate_qt.cpp \
web_contents_view_qt.cpp \
web_engine_context.cpp \
+ web_engine_context_threads.cpp \
web_engine_error.cpp \
web_engine_library_info.cpp \
web_engine_settings.cpp \
web_event_factory.cpp
HEADERS = \
+ accessibility_activation_observer.h \
authentication_dialog_controller_p.h \
authentication_dialog_controller.h \
build_config_qt.h \
@@ -137,6 +146,8 @@ HEADERS = \
certificate_error_controller_p.h \
certificate_error_controller.h \
chromium_overrides.h \
+ client_cert_override_key_p.h \
+ client_cert_override_p.h \
client_cert_select_controller.h \
clipboard_qt.h \
color_chooser_qt.h \
@@ -144,35 +155,38 @@ HEADERS = \
color_chooser_controller.h \
common/qt_messages.h \
common/user_script_data.h \
- compositor.h \
+ compositor/chromium_gpu_helper.h \
+ compositor/compositor.h \
+ compositor/compositor_resource.h \
+ compositor/compositor_resource_tracker.h \
+ compositor/content_gpu_client_qt.h \
+ compositor/delegated_frame_node.h \
content_client_qt.h \
content_browser_client_qt.h \
content_main_delegate_qt.h \
content_utility_client_qt.h \
- delegated_frame_node.h \
desktop_screen_qt.h \
devtools_frontend_qt.h \
devtools_manager_delegate_qt.h \
download_manager_delegate_qt.h \
- chromium_gpu_helper.h \
favicon_manager.h \
file_picker_controller.h \
global_descriptors_qt.h \
javascript_dialog_controller_p.h \
javascript_dialog_controller.h \
javascript_dialog_manager_qt.h \
+ locked_ptr.h \
login_delegate_qt.h \
media_capture_devices_dispatcher.h \
net/cookie_monster_delegate_qt.h \
net/custom_protocol_handler.h \
net/network_delegate_qt.h \
- net/qrc_protocol_handler_qt.h \
+ net/qrc_url_scheme_handler.h \
net/ssl_host_state_delegate_qt.h \
net/url_request_context_getter_qt.h \
net/url_request_custom_job.h \
net/url_request_custom_job_delegate.h \
net/url_request_custom_job_proxy.h \
- net/url_request_qrc_job_qt.h \
net/webui_controller_factory_qt.h \
ozone/gl_context_qt.h \
ozone/gl_ozone_egl_qt.h \
@@ -207,6 +221,10 @@ HEADERS = \
request_controller.h \
resource_context_qt.h \
service/service_qt.h \
+ touch_handle_drawable_client.h \
+ touch_handle_drawable_qt.h \
+ touch_selection_controller_client_qt.h \
+ touch_selection_menu_controller.h \
type_conversion.h \
user_script.h \
visited_links_manager_qt.h \
@@ -266,12 +284,14 @@ qtConfig(webengine-printing-and-pdf) {
contains(QT_CONFIG, opengl) {
SOURCES += \
- yuv_video_node.cpp \
- stream_video_node.cpp
+ compositor/compositor_resource_fence.cpp \
+ compositor/stream_video_node.cpp \
+ compositor/yuv_video_node.cpp
HEADERS += \
- yuv_video_node.h \
- stream_video_node.h
+ compositor/compositor_resource_fence.h \
+ compositor/stream_video_node.h \
+ compositor/yuv_video_node.h
}
qtConfig(webengine-geolocation) {
diff --git a/src/core/devtools_frontend_qt.cpp b/src/core/devtools_frontend_qt.cpp
index bd9e0ebe7..40e30e008 100644
--- a/src/core/devtools_frontend_qt.cpp
+++ b/src/core/devtools_frontend_qt.cpp
@@ -56,11 +56,13 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/post_task.h"
#include "base/values.h"
#include "chrome/common/url_constants.h"
#include "components/prefs/in_memory_pref_store.h"
#include "components/prefs/json_pref_store.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_handle.h"
@@ -109,9 +111,9 @@ public:
~ResponseWriter() override;
// URLFetcherResponseWriter overrides:
- int Initialize(const net::CompletionCallback &callback) override;
- int Write(net::IOBuffer *buffer, int num_bytes, const net::CompletionCallback &callback) override;
- int Finish(int net_error, const net::CompletionCallback &callback) override;
+ int Initialize(net::CompletionOnceCallback callback) override;
+ int Write(net::IOBuffer *buffer, int num_bytes, net::CompletionOnceCallback callback) override;
+ int Finish(int net_error, net::CompletionOnceCallback callback) override;
private:
base::WeakPtr<DevToolsFrontendQt> shell_devtools_;
@@ -126,12 +128,12 @@ ResponseWriter::ResponseWriter(base::WeakPtr<DevToolsFrontendQt> shell_devtools,
ResponseWriter::~ResponseWriter() {}
-int ResponseWriter::Initialize(const net::CompletionCallback& callback)
+int ResponseWriter::Initialize(net::CompletionOnceCallback callback)
{
return net::OK;
}
-int ResponseWriter::Write(net::IOBuffer *buffer, int num_bytes, const net::CompletionCallback &callback)
+int ResponseWriter::Write(net::IOBuffer *buffer, int num_bytes, net::CompletionOnceCallback callback)
{
std::string chunk = std::string(buffer->data(), num_bytes);
if (!base::IsStringUTF8(chunk))
@@ -140,15 +142,15 @@ int ResponseWriter::Write(net::IOBuffer *buffer, int num_bytes, const net::Compl
base::Value *id = new base::Value(stream_id_);
base::Value *chunkValue = new base::Value(chunk);
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(&DevToolsFrontendQt::CallClientFunction,
shell_devtools_, "DevToolsAPI.streamWrite",
base::Owned(id), base::Owned(chunkValue), nullptr));
return num_bytes;
}
-int ResponseWriter::Finish(int net_error, const net::CompletionCallback &callback)
+int ResponseWriter::Finish(int net_error, net::CompletionOnceCallback callback)
{
return net::OK;
}
diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp
index 948a62047..398bde710 100644
--- a/src/core/download_manager_delegate_qt.cpp
+++ b/src/core/download_manager_delegate_qt.cpp
@@ -164,7 +164,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem*
suggestedFilename += QStringLiteral(".") + mimeType.preferredSuffix();
}
- QDir defaultDownloadDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+ QDir defaultDownloadDirectory(m_profileAdapter->downloadPath());
QFileInfo suggestedFile(defaultDownloadDirectory.absoluteFilePath(suggestedFilename));
QString suggestedFilePath = suggestedFile.absoluteFilePath();
diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp
index 3ded5ec41..a495ce6f2 100644
--- a/src/core/file_picker_controller.cpp
+++ b/src/core/file_picker_controller.cpp
@@ -41,6 +41,7 @@
#include "type_conversion.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/file_select_listener.h"
#include <QFileInfo>
#include <QDir>
@@ -49,18 +50,20 @@
namespace QtWebEngineCore {
-FilePickerController::FilePickerController(FileChooserMode mode, content::RenderFrameHost *frameHost, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject *parent)
+FilePickerController::FilePickerController(FileChooserMode mode, std::unique_ptr<content::FileSelectListener> listener, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject *parent)
: QObject(parent)
, m_defaultFileName(defaultFileName)
, m_acceptedMimeTypes(acceptedMimeTypes)
- , m_frameHost(frameHost)
+ , m_listener(std::move(listener))
, m_mode(mode)
{
}
+FilePickerController::~FilePickerController() = default;
+
void FilePickerController::accepted(const QStringList &files)
{
- FilePickerController::filesSelectedInChooser(files, m_frameHost);
+ FilePickerController::filesSelectedInChooser(files);
}
void FilePickerController::accepted(const QVariant &files)
@@ -77,12 +80,12 @@ void FilePickerController::accepted(const QVariant &files)
qWarning("An unhandled type '%s' was provided in FilePickerController::accepted(QVariant)", files.typeName());
}
- FilePickerController::filesSelectedInChooser(stringList, m_frameHost);
+ FilePickerController::filesSelectedInChooser(stringList);
}
void FilePickerController::rejected()
{
- FilePickerController::filesSelectedInChooser(QStringList(), m_frameHost);
+ FilePickerController::filesSelectedInChooser(QStringList());
}
static QStringList listRecursively(const QDir &dir)
@@ -99,19 +102,29 @@ static QStringList listRecursively(const QDir &dir)
return ret;
}
-ASSERT_ENUMS_MATCH(FilePickerController::Open, content::FileChooserParams::Open)
-ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, content::FileChooserParams::OpenMultiple)
-ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, content::FileChooserParams::UploadFolder)
-ASSERT_ENUMS_MATCH(FilePickerController::Save, content::FileChooserParams::Save)
+ASSERT_ENUMS_MATCH(FilePickerController::Open, blink::mojom::FileChooserParams_Mode::kOpen)
+ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, blink::mojom::FileChooserParams_Mode::kOpenMultiple)
+ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, blink::mojom::FileChooserParams_Mode::kUploadFolder)
+ASSERT_ENUMS_MATCH(FilePickerController::Save, blink::mojom::FileChooserParams_Mode::kSave)
-void FilePickerController::filesSelectedInChooser(const QStringList &filesList, content::RenderFrameHost *frameHost)
+void FilePickerController::filesSelectedInChooser(const QStringList &filesList)
{
- Q_ASSERT(frameHost);
QStringList files(filesList);
if (this->m_mode == UploadFolder && !filesList.isEmpty()
&& QFileInfo(filesList.first()).isDir()) // Enumerate the directory
files = listRecursively(QDir(filesList.first()));
- frameHost->FilesSelectedInChooser(toVector<content::FileChooserFileInfo>(files), static_cast<content::FileChooserParams::Mode>(this->m_mode));
+
+ std::vector<blink::mojom::FileChooserFileInfoPtr> chooser_files;
+ for (const auto &file : qAsConst(files)) {
+ chooser_files.push_back(blink::mojom::FileChooserFileInfo::NewNativeFile(
+ blink::mojom::NativeFileInfo::New(toFilePath(file), base::string16())));
+ }
+
+ if (files.isEmpty())
+ m_listener->FileSelectionCanceled();
+ else
+ m_listener->FileSelected(std::move(chooser_files),
+ static_cast<blink::mojom::FileChooserParams::Mode>(this->m_mode));
}
QStringList FilePickerController::acceptedMimeTypes() const
diff --git a/src/core/file_picker_controller.h b/src/core/file_picker_controller.h
index 7507cf358..613d3ad9b 100644
--- a/src/core/file_picker_controller.h
+++ b/src/core/file_picker_controller.h
@@ -52,11 +52,14 @@
#define FILE_PICKER_CONTROLLER_H
#include "qtwebenginecoreglobal_p.h"
+
+#include <memory>
+
#include <QObject>
#include <QStringList>
namespace content {
- class RenderFrameHost;
+ class FileSelectListener;
}
namespace QtWebEngineCore {
@@ -71,7 +74,8 @@ public:
Save
};
- FilePickerController(FileChooserMode mode, content::RenderFrameHost *contents, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject * = 0);
+ FilePickerController(FileChooserMode mode, std::unique_ptr<content::FileSelectListener> listener, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject * = 0);
+ ~FilePickerController() override;
QStringList acceptedMimeTypes() const;
QString defaultFileName() const;
FileChooserMode mode() const;
@@ -82,10 +86,10 @@ public Q_SLOTS:
void rejected();
private:
- void filesSelectedInChooser(const QStringList &filesList, content::RenderFrameHost *contents);
+ void filesSelectedInChooser(const QStringList &filesList);
QString m_defaultFileName;
QStringList m_acceptedMimeTypes;
- content::RenderFrameHost *m_frameHost;
+ std::unique_ptr<content::FileSelectListener> m_listener;
FileChooserMode m_mode;
};
diff --git a/src/core/locked_ptr.h b/src/core/locked_ptr.h
new file mode 100644
index 000000000..46d89819b
--- /dev/null
+++ b/src/core/locked_ptr.h
@@ -0,0 +1,301 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LOCKED_PTR_H
+#define LOCKED_PTR_H
+
+#include <base/bind_internal.h>
+
+#include <QtCore/qreadwritelock.h>
+
+namespace base {
+
+struct LockedPtrCore
+{
+ LockedPtrCore(uintptr_t data) : data(data) {}
+
+ std::atomic<size_t> refCount{1};
+ // Atomic so that WeakLockedPtr::get can still read it.
+ std::atomic<uintptr_t> data;
+ QReadWriteLock lock{QReadWriteLock::Recursive};
+};
+
+enum class LockedPtrMode { Weak, Shared, Exclusive };
+
+template<class T, LockedPtrMode mode> class LockedPtr;
+
+// A WeakLockedPtr<T> is something like shared_ptr<T*>. The T* value can only be
+// accessed by atomic read.
+template<class T> using WeakLockedPtr = LockedPtr<T, LockedPtrMode::Weak>;
+
+// A SharedLockedPtr<T> is like WeakLockedPtr<T>, but the T* value is prevented
+// from changing for the lifetime of the SharedLockedPtr by holding a
+// shared-exclusive mutex in shared mode.
+template<class T> using SharedLockedPtr = LockedPtr<T, LockedPtrMode::Shared>;
+
+// An ExclusiveLockedPtr<T> is like SharedLockedPtr<T>, but the mutex is held in
+// exclusive mode. Only in this mode can the T* value be changed.
+template<class T> using ExclusiveLockedPtr = LockedPtr<T, LockedPtrMode::Exclusive>;
+
+template<class T, LockedPtrMode mode>
+class LockedPtr
+{
+ template<class T1>
+ static constexpr bool canConstructFrom =
+ std::is_same<T, T1>::value ||
+ std::is_same<T, const T1>::value;
+
+public:
+ constexpr LockedPtr() {}
+ constexpr LockedPtr(std::nullptr_t) {}
+
+ LockedPtr(const LockedPtr &that)
+ {
+ m_core = that.m_core;
+ lock();
+ }
+
+ LockedPtr &operator=(const LockedPtr &that)
+ {
+ unlock();
+ m_core = that.m_core;
+ lock();
+ }
+
+ LockedPtr(LockedPtr &&that)
+ {
+ m_core = that.m_core;
+ that.m_core = nullptr;
+ }
+
+ LockedPtr &operator=(LockedPtr &&that)
+ {
+ unlock();
+ m_core = that.m_core;
+ that.m_core = nullptr;
+ }
+
+ template<class T1, LockedPtrMode mode1,
+ class Enable = std::enable_if_t<canConstructFrom<T1>>>
+ LockedPtr(const LockedPtr<T1, mode1> &that)
+ {
+ m_core = that.m_core;
+ lock();
+ }
+
+ template<class T1, LockedPtrMode mode1,
+ class Enable = std::enable_if_t<canConstructFrom<T1>>>
+ LockedPtr &operator=(const LockedPtr<T1, mode1> &that)
+ {
+ unlock();
+ m_core = that.m_core;
+ lock();
+ }
+
+ template<class T1,
+ class Enable = std::enable_if_t<canConstructFrom<T1>>>
+ LockedPtr(LockedPtr<T1, mode> &&that)
+ {
+ m_core = that.m_core;
+ that.m_core = nullptr;
+ }
+
+ template<class T1,
+ class Enable = std::enable_if_t<canConstructFrom<T1>>>
+ LockedPtr &operator=(LockedPtr<T1, mode> &&that)
+ {
+ unlock();
+ m_core = that.m_core;
+ that.m_core = nullptr;
+ }
+
+ ~LockedPtr()
+ {
+ unlock();
+ }
+
+ T *get() const
+ {
+ if (m_core) {
+ if (mode == LockedPtrMode::Weak)
+ return reinterpret_cast<T *>(m_core->data.load(std::memory_order_acquire));
+ else
+ return reinterpret_cast<T *>(m_core->data.load(std::memory_order_relaxed));
+ }
+ return nullptr;
+ }
+
+ void set(T *value)
+ {
+ static_assert(mode == LockedPtrMode::Exclusive, "");
+ DCHECK(m_core);
+ m_core->data.store(reinterpret_cast<uintptr_t>(value), std::memory_order_release);
+ }
+
+ T &operator*() const { return *get(); }
+ T *operator->() const { return get(); }
+ explicit operator bool() const { return get(); }
+
+ bool MaybeValid() const { return m_core; }
+
+ static LockedPtr create(T *value)
+ {
+ return new LockedPtrCore(reinterpret_cast<uintptr_t>(value));
+ }
+
+private:
+ template<class T1, LockedPtrMode mode1> friend class LockedPtr;
+
+ LockedPtr(LockedPtrCore *core)
+ : m_core(core)
+ {}
+
+ void lock()
+ {
+ if (m_core) {
+ ++m_core->refCount;
+
+ if (mode == LockedPtrMode::Shared)
+ m_core->lock.lockForRead();
+ else if (mode == LockedPtrMode::Exclusive)
+ m_core->lock.lockForWrite();
+ }
+ }
+
+ void unlock()
+ {
+ if (m_core) {
+ if (mode != LockedPtrMode::Weak)
+ m_core->lock.unlock();
+
+ if (--m_core->refCount == 0)
+ delete m_core;
+ }
+ }
+
+ LockedPtrCore *m_core = nullptr;
+};
+
+// This makes Bind check the pointer before calling the functor.
+template<class T>
+struct IsWeakReceiver<WeakLockedPtr<T>> : std::true_type {};
+
+// By converting the WeakLockedPtr into a SharedLockedPtr we prevent the
+// pointed-to object from being destroyed during the base::Callback::Run call.
+//
+// Unwrap() is called before checking the pointer, so there's no race condition.
+template<class T>
+struct BindUnwrapTraits<WeakLockedPtr<T>>
+{
+ static SharedLockedPtr<T> Unwrap(const WeakLockedPtr<T> &o)
+ {
+ return o;
+ }
+};
+
+// Like base::WeakPtrFactory, but InvalidateWeakPtrs *waits* until all currently
+// executing base::Callbacks are finished. Queued up base::Callbacks are still
+// canceled, exactly like with WeakPtrFactory.
+//
+// Consider, for example, the function
+//
+// void fun()
+// {
+// MyClass *myClass = new MyClass;
+// myClass->scheduleDoStuff();
+// delete myClass; // ???
+// }
+//
+// where
+//
+// class MyClass
+// {
+// public:
+// void scheduleDoStuff()
+// {
+// content::BrowserThread::PostTask(
+// content::BrowserThread::IO, FROM_HERE,
+// base::BindOnce(&MyClass::doStuff, m_weakPtrFactory.GetWeakPtr()));
+// }
+// void doStuff();
+// private:
+// //base::WeakPtrFactory m_weakPtrFactory{this};
+// base::LockedPtrFactory m_weakPtrFactory{this};
+// };
+//
+// What happens if the 'delete myClass' line is executed concurrently with
+// MyClass::doStuff?
+//
+// With WeakPtrs we get a segfault or perhaps memory corruption.
+//
+// With LockedPtrs we get no crash and no corruption: LockedPtrFactory's
+// destructor will wait until doStuff is done before continuing.
+template<class T>
+class LockedPtrFactory
+{
+public:
+ explicit LockedPtrFactory(T *value)
+ : m_ptr(WeakLockedPtr<T>::create(value))
+ {}
+
+ ~LockedPtrFactory()
+ {
+ InvalidateWeakPtrs();
+ }
+
+ WeakLockedPtr<T> GetWeakPtr() { return m_ptr; }
+ WeakLockedPtr<const T> GetWeakPtr() const { return m_ptr; }
+ SharedLockedPtr<T> GetSharedPtr() { return m_ptr; }
+ SharedLockedPtr<const T> GetSharedPtr() const { return m_ptr; }
+ ExclusiveLockedPtr<T> GetExclusivePtr() { return m_ptr; }
+ ExclusiveLockedPtr<const T> GetExclusivePtr() const { return m_ptr; }
+
+ void InvalidateWeakPtrs()
+ {
+ if (ExclusiveLockedPtr<T> ptr = m_ptr)
+ ptr.set(nullptr);
+ }
+
+private:
+ WeakLockedPtr<T> m_ptr;
+};
+
+} // namespace base
+
+#endif // !LOCKED_PTR_H
diff --git a/src/core/login_delegate_qt.cpp b/src/core/login_delegate_qt.cpp
index 9659b354a..31824ca71 100644
--- a/src/core/login_delegate_qt.cpp
+++ b/src/core/login_delegate_qt.cpp
@@ -43,7 +43,9 @@
#include "login_delegate_qt.h"
+#include "base/task/post_task.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_dispatcher_host.h"
@@ -66,14 +68,9 @@ LoginDelegateQt::LoginDelegateQt(
: m_authInfo(authInfo)
, m_url(url)
, m_auth_required_callback(std::move(auth_required_callback))
+ , m_webContentsGetter(web_contents_getter)
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::Bind(&LoginDelegateQt::triggerDialog,
- this,
- web_contents_getter));
}
LoginDelegateQt::~LoginDelegateQt()
@@ -81,6 +78,13 @@ LoginDelegateQt::~LoginDelegateQt()
Q_ASSERT(m_dialogController.isNull());
}
+void LoginDelegateQt::triggerDialog()
+{
+ base::PostTaskWithTraits(
+ FROM_HERE, { content::BrowserThread::UI },
+ base::BindOnce(&LoginDelegateQt::triggerDialogOnUI, this));
+}
+
void LoginDelegateQt::OnRequestCancelled()
{
destroy();
@@ -107,11 +111,11 @@ bool LoginDelegateQt::isProxy() const
return m_authInfo->is_proxy;
}
-void LoginDelegateQt::triggerDialog(const content::ResourceRequestInfo::WebContentsGetter &webContentsGetter)
+void LoginDelegateQt::triggerDialogOnUI()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
content::WebContentsImpl *webContents =
- static_cast<content::WebContentsImpl *>(webContentsGetter.Run());
+ static_cast<content::WebContentsImpl *>(m_webContentsGetter.Run());
if (!webContents)
return;
WebContentsAdapterClient *client = WebContentsViewQt::from(webContents->GetView())->client();
diff --git a/src/core/login_delegate_qt.h b/src/core/login_delegate_qt.h
index 9ce5df843..ccd1f7322 100644
--- a/src/core/login_delegate_qt.h
+++ b/src/core/login_delegate_qt.h
@@ -66,6 +66,8 @@ public:
~LoginDelegateQt();
+ void triggerDialog();
+
// LoginDelegate implementation
void OnRequestCancelled() override;
@@ -77,13 +79,14 @@ public:
void sendAuthToRequester(bool success, const QString &user, const QString &password);
private:
- void triggerDialog(const content::ResourceRequestInfo::WebContentsGetter &);
+ void triggerDialogOnUI();
void destroy();
scoped_refptr<net::AuthChallengeInfo> m_authInfo;
GURL m_url;
LoginAuthRequiredCallback m_auth_required_callback;
+ content::ResourceRequestInfo::WebContentsGetter m_webContentsGetter;
// This member is used to keep authentication dialog controller alive until
// authorization is sent or cancelled.
diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp
index 2bac62084..a0b19cad3 100644
--- a/src/core/media_capture_devices_dispatcher.cpp
+++ b/src/core/media_capture_devices_dispatcher.cpp
@@ -49,10 +49,10 @@
#include "web_engine_settings.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/media/webrtc/desktop_streams_registry.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_media_id.h"
+#include "content/public/browser/desktop_streams_registry.h"
#include "content/public/browser/media_capture_devices.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
@@ -95,16 +95,16 @@ void getDevicesForDesktopCapture(content::MediaStreamDevices *devices, content::
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Add selected desktop source to the list.
- devices->push_back(content::MediaStreamDevice(content::MEDIA_DESKTOP_VIDEO_CAPTURE, mediaId.ToString(), "Screen"));
+ devices->push_back(content::MediaStreamDevice(content::MEDIA_GUM_DESKTOP_VIDEO_CAPTURE, mediaId.ToString(), "Screen"));
if (captureAudio) {
if (mediaId.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) {
devices->push_back(
- content::MediaStreamDevice(content::MEDIA_DESKTOP_AUDIO_CAPTURE,
+ content::MediaStreamDevice(content::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE,
mediaId.ToString(), "Tab audio"));
} else {
// Use the special loopback device ID for system audio capture.
devices->push_back(content::MediaStreamDevice(
- content::MEDIA_DESKTOP_AUDIO_CAPTURE,
+ content::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE,
media::AudioDeviceDescription::kLoopbackInputDeviceId,
"System Audio"));
}
@@ -157,12 +157,12 @@ WebContentsAdapterClient::MediaRequestFlags mediaRequestFlagsForRequest(const co
if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE)
requestFlags |= WebContentsAdapterClient::MediaAudioCapture;
- else if (request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE)
+ else if (request.audio_type == content::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE)
requestFlags |= WebContentsAdapterClient::MediaDesktopAudioCapture;
if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE)
requestFlags |= WebContentsAdapterClient::MediaVideoCapture;
- else if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE)
+ else if (request.video_type == content::MEDIA_GUM_DESKTOP_VIDEO_CAPTURE)
requestFlags |= WebContentsAdapterClient::MediaDesktopVideoCapture;
return requestFlags;
@@ -233,8 +233,9 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content:
// Post a task to process next queued request. It has to be done
// asynchronously to make sure that calling infobar is not destroyed until
// after this function returns.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::BindOnce(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, base::Unretained(this), webContents));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest,
+ base::Unretained(this), webContents));
}
std::move(callback).Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK,
@@ -275,12 +276,12 @@ void MediaCaptureDevicesDispatcher::processMediaAccessRequest(WebContentsAdapter
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Let's not support tab capture for now.
- if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE || request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) {
+ if (request.video_type == content::MEDIA_GUM_TAB_VIDEO_CAPTURE || request.audio_type == content::MEDIA_GUM_TAB_AUDIO_CAPTURE) {
std::move(callback).Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_NOT_SUPPORTED, std::unique_ptr<content::MediaStreamUI>());
return;
}
- if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) {
+ if (request.video_type == content::MEDIA_GUM_DESKTOP_VIDEO_CAPTURE || request.audio_type == content::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE) {
const bool screenCaptureEnabled =
adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::ScreenCaptureEnabled);
const bool originIsSecure = content::IsOriginSecure(request.security_origin);
@@ -305,7 +306,7 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::
{
content::MediaStreamDevices devices;
- if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.requested_video_device_id.empty()) {
+ if (request.video_type != content::MEDIA_GUM_DESKTOP_VIDEO_CAPTURE || request.requested_video_device_id.empty()) {
std::move(callback).Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>());
return;
}
@@ -319,10 +320,10 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::
// The extension name that the stream is registered with.
std::string originalExtensionName;
// Resolve DesktopMediaID for the specified device id.
- mediaId = getDesktopStreamsRegistry()->RequestMediaForStreamId(
+ mediaId = content::DesktopStreamsRegistry::GetInstance()->RequestMediaForStreamId(
request.requested_video_device_id, main_frame->GetProcess()->GetID(),
main_frame->GetRoutingID(), request.security_origin,
- &originalExtensionName);
+ &originalExtensionName, content::kRegistryStreamTypeDesktop);
}
// Received invalid device id.
@@ -332,7 +333,7 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::
}
// Audio is only supported for screen capture streams.
- bool capture_audio = (mediaId.type == content::DesktopMediaID::TYPE_SCREEN && request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE);
+ bool capture_audio = (mediaId.type == content::DesktopMediaID::TYPE_SCREEN && request.audio_type == content::MEDIA_GUM_DESKTOP_AUDIO_CAPTURE);
getDevicesForDesktopCapture(&devices, mediaId, capture_audio);
@@ -390,22 +391,13 @@ void MediaCaptureDevicesDispatcher::getDefaultDevices(const std::string &audioDe
}
}
-DesktopStreamsRegistry *MediaCaptureDevicesDispatcher::getDesktopStreamsRegistry()
-{
- if (!m_desktopStreamsRegistry)
- m_desktopStreamsRegistry.reset(new DesktopStreamsRegistry());
- return m_desktopStreamsRegistry.get();
-}
-
void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(int render_process_id, int render_frame_id, int page_request_id, const GURL &security_origin, content::MediaStreamType stream_type, content::MediaRequestState state)
{
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread,
- base::Unretained(this), render_process_id, render_frame_id,
- page_request_id, security_origin, stream_type, state));
+ base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread,
+ base::Unretained(this), render_process_id, render_frame_id,
+ page_request_id, security_origin, stream_type, state));
}
void MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread(int render_process_id,
diff --git a/src/core/media_capture_devices_dispatcher.h b/src/core/media_capture_devices_dispatcher.h
index 0e5aa38be..cc6e60ede 100644
--- a/src/core/media_capture_devices_dispatcher.h
+++ b/src/core/media_capture_devices_dispatcher.h
@@ -57,8 +57,6 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/media_stream_request.h"
-class DesktopStreamsRegistry;
-
namespace QtWebEngineCore {
// This singleton is used to receive updates about media events from the content
@@ -94,8 +92,6 @@ private:
content::MediaStreamType /*stream_type*/,
bool /*is_secure*/) override {}
- DesktopStreamsRegistry *getDesktopStreamsRegistry();
-
friend struct base::DefaultSingletonTraits<MediaCaptureDevicesDispatcher>;
typedef base::RepeatingCallback<void(const content::MediaStreamDevices &devices,
@@ -129,8 +125,6 @@ private:
RequestsQueues m_pendingRequests;
- std::unique_ptr<DesktopStreamsRegistry> m_desktopStreamsRegistry;
-
content::NotificationRegistrar m_notificationsRegistrar;
DISALLOW_COPY_AND_ASSIGN(MediaCaptureDevicesDispatcher);
diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp
index bb89e9e5f..3253b08b9 100644
--- a/src/core/net/cookie_monster_delegate_qt.cpp
+++ b/src/core/net/cookie_monster_delegate_qt.cpp
@@ -41,6 +41,8 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/cookies/cookie_util.h"
@@ -87,8 +89,8 @@ void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId)
net::CookieMonster::GetCookieListCallback callback =
base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread, this, callbackId);
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, std::move(callback)));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, std::move(callback)));
}
void CookieMonsterDelegateQt::GetAllCookiesOnIOThread(net::CookieMonster::GetCookieListCallback callback)
@@ -108,9 +110,9 @@ void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie
GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin);
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CookieMonsterDelegateQt::SetCookieOnIOThread, this,
- gurl, cookie.toRawForm().toStdString(), std::move(callback)));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&CookieMonsterDelegateQt::SetCookieOnIOThread, this,
+ gurl, cookie.toRawForm().toStdString(), std::move(callback)));
}
void CookieMonsterDelegateQt::SetCookieOnIOThread(
@@ -131,9 +133,9 @@ void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const Q
GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin);
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this,
- gurl, cookie.name().toStdString()));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this,
+ gurl, cookie.name().toStdString()));
}
void CookieMonsterDelegateQt::DeleteCookieOnIOThread(const GURL& url, const std::string& cookie_name)
@@ -149,8 +151,8 @@ void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId)
net::CookieMonster::DeleteCallback callback =
base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId);
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, std::move(callback)));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, std::move(callback)));
}
void CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread(net::CookieMonster::DeleteCallback callback)
@@ -166,8 +168,8 @@ void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId)
net::CookieMonster::DeleteCallback callback =
base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread, this, callbackId);
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, std::move(callback)));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, std::move(callback)));
}
void CookieMonsterDelegateQt::DeleteAllOnIOThread(net::CookieMonster::DeleteCallback callback)
@@ -238,26 +240,23 @@ void CookieMonsterDelegateQt::GetAllCookiesCallbackOnIOThread(qint64 callbackId,
for (auto &&cookie : cookies)
rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n");
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
- FROM_HERE,
- base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId, rawCookies));
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread, this, callbackId, rawCookies));
}
void CookieMonsterDelegateQt::SetCookieCallbackOnIOThread(qint64 callbackId, bool success)
{
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
- FROM_HERE,
- base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId, success));
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&CookieMonsterDelegateQt::SetCookieCallbackOnUIThread, this, callbackId, success));
}
void CookieMonsterDelegateQt::DeleteCookiesCallbackOnIOThread(qint64 callbackId, uint numCookies)
{
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
- FROM_HERE,
- base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId, numCookies));
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&CookieMonsterDelegateQt::DeleteCookiesCallbackOnUIThread, this, callbackId, numCookies));
}
void CookieMonsterDelegateQt::GetAllCookiesCallbackOnUIThread(qint64 callbackId, const QByteArray &cookies)
diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp
index 37309931e..73f3ff818 100644
--- a/src/core/net/network_delegate_qt.cpp
+++ b/src/core/net/network_delegate_qt.cpp
@@ -39,16 +39,19 @@
#include "network_delegate_qt.h"
-#include "profile_adapter.h"
+#include "base/task/post_task.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_request_info.h"
-#include "cookie_monster_delegate_qt.h"
-#include "ui/base/page_transition_types.h"
-#include "profile_io_data_qt.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
+#include "ui/base/page_transition_types.h"
+
+#include "profile_adapter.h"
+#include "cookie_monster_delegate_qt.h"
+#include "profile_io_data_qt.h"
#include "qwebengineurlrequestinfo.h"
#include "qwebengineurlrequestinfo_p.h"
#include "qwebengineurlrequestinterceptor.h"
@@ -81,16 +84,19 @@ WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::Page
}
}
-namespace {
-
-QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType)
+static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourceType)
{
if (resourceType >= 0 && resourceType < content::ResourceType(QWebEngineUrlRequestInfo::ResourceTypeLast))
return static_cast<QWebEngineUrlRequestInfo::ResourceType>(resourceType);
return QWebEngineUrlRequestInfo::ResourceTypeUnknown;
}
-QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType)
+static content::ResourceType fromQt(QWebEngineUrlRequestInfo::ResourceType resourceType)
+{
+ return static_cast<content::ResourceType>(resourceType);
+}
+
+static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType)
{
return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType);
}
@@ -99,26 +105,27 @@ QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::Navigati
class URLRequestNotification {
public:
URLRequestNotification(net::URLRequest *request,
- const QUrl &url,
bool isMainFrameRequest,
- int navigationType,
- int frameTreeNodeId,
+ GURL *newUrl,
+ QWebEngineUrlRequestInfo &&requestInfo,
+ content::ResourceRequestInfo::WebContentsGetter webContentsGetter,
net::CompletionOnceCallback callback)
: m_request(request)
- , m_url(url)
, m_isMainFrameRequest(isMainFrameRequest)
- , m_navigationType(navigationType)
- , m_frameTreeNodeId(frameTreeNodeId)
+ , m_newUrl(newUrl)
+ , m_originalUrl(requestInfo.requestUrl())
+ , m_requestInfo(std::move(requestInfo))
+ , m_webContentsGetter(webContentsGetter)
, m_callback(std::move(callback))
{
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
m_request->SetUserData(UserData::key, std::make_unique<UserData>(this));
- content::BrowserThread::PostTask(
- content::BrowserThread::UI,
+ base::PostTaskWithTraits(
FROM_HERE,
- base::Bind(&URLRequestNotification::notify, base::Unretained(this)));
+ {content::BrowserThread::UI},
+ base::BindOnce(&URLRequestNotification::notify, base::Unretained(this)));
}
private:
@@ -148,31 +155,42 @@ private:
// May run concurrently with cancel() so no peeking at m_request here.
int error = net::OK;
- content::WebContents *webContents = content::WebContents::FromFrameTreeNodeId(m_frameTreeNodeId);
+ content::WebContents *webContents = m_webContentsGetter.Run();
+
if (webContents) {
- int navigationRequestAction = WebContentsAdapterClient::AcceptRequest;
WebContentsAdapterClient *client =
- WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client();
- client->navigationRequested(m_navigationType,
- m_url,
- navigationRequestAction,
- m_isMainFrameRequest);
- error = net::ERR_FAILED;
- switch (static_cast<WebContentsAdapterClient::NavigationRequestAction>(navigationRequestAction)) {
- case WebContentsAdapterClient::AcceptRequest:
- error = net::OK;
- break;
- case WebContentsAdapterClient::IgnoreRequest:
- error = net::ERR_ABORTED;
- break;
+ WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client();
+
+ client->interceptRequest(m_requestInfo);
+ if (m_requestInfo.changed()) {
+ error = m_requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
+ // We handle the rest of the changes later when we are back in I/O thread
+ }
+
+ // Only do navigationRequested on MAIN_FRAME and SUB_FRAME resources
+ if (error == net::OK && content::IsResourceTypeFrame(fromQt(m_requestInfo.resourceType()))) {
+ int navigationRequestAction = WebContentsAdapterClient::AcceptRequest;
+ client->navigationRequested(m_requestInfo.navigationType(),
+ m_requestInfo.requestUrl(),
+ navigationRequestAction,
+ m_isMainFrameRequest);
+ error = net::ERR_FAILED;
+ switch (static_cast<WebContentsAdapterClient::NavigationRequestAction>(navigationRequestAction)) {
+ case WebContentsAdapterClient::AcceptRequest:
+ error = net::OK;
+ break;
+ case WebContentsAdapterClient::IgnoreRequest:
+ error = net::ERR_ABORTED;
+ break;
+ }
+ DCHECK(error != net::ERR_FAILED);
}
- DCHECK(error != net::ERR_FAILED);
}
// Run the callback on the IO thread.
- content::BrowserThread::PostTask(
- content::BrowserThread::IO,
+ base::PostTaskWithTraits(
FROM_HERE,
+ {content::BrowserThread::IO},
base::BindOnce(&URLRequestNotification::complete, base::Unretained(this), error));
}
@@ -181,6 +199,17 @@ private:
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (m_request) {
+ if (m_requestInfo.changed()) {
+ if (m_originalUrl != m_requestInfo.d_ptr->url)
+ *m_newUrl = toGurl(m_requestInfo.d_ptr->url);
+
+ if (!m_requestInfo.d_ptr->extraHeaders.isEmpty()) {
+ auto end = m_requestInfo.d_ptr->extraHeaders.constEnd();
+ for (auto header = m_requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header)
+ m_request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true);
+ }
+ }
+
if (m_request->status().status() != net::URLRequestStatus::CANCELED)
std::move(m_callback).Run(error);
m_request->RemoveUserData(UserData::key);
@@ -192,17 +221,16 @@ private:
~URLRequestNotification() {}
net::URLRequest *m_request;
- QUrl m_url;
bool m_isMainFrameRequest;
- int m_navigationType;
- int m_frameTreeNodeId;
+ GURL *m_newUrl;
+ const QUrl m_originalUrl;
+ QWebEngineUrlRequestInfo m_requestInfo;
+ content::ResourceRequestInfo::WebContentsGetter m_webContentsGetter;
net::CompletionOnceCallback m_callback;
};
const char URLRequestNotification::UserData::key[] = "QtWebEngineCore::URLRequestNotification";
-} // namespace
-
NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data)
: m_profileIOData(data)
{
@@ -212,7 +240,6 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_profileIOData);
-
const content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request);
content::ResourceType resourceType = content::RESOURCE_TYPE_LAST_TYPE;
@@ -231,14 +258,14 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
else
firstPartyUrl = toQt(request->site_for_cookies());
- QWebEngineUrlRequestInterceptor* interceptor = m_profileIOData->acquireInterceptor();
- if (interceptor) {
- QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType),
- toQt(navigationType),
- qUrl,
- firstPartyUrl,
- QByteArray::fromStdString(request->method()));
- QWebEngineUrlRequestInfo requestInfo(infoPrivate);
+ QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType),
+ toQt(navigationType),
+ qUrl,
+ firstPartyUrl,
+ QByteArray::fromStdString(request->method()));
+ QWebEngineUrlRequestInfo requestInfo(infoPrivate);
+
+ if (QWebEngineUrlRequestInterceptor* interceptor = m_profileIOData->acquireInterceptor()) {
interceptor->interceptRequest(requestInfo);
m_profileIOData->releaseInterceptor();
if (requestInfo.changed()) {
@@ -255,6 +282,8 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
if (result != net::OK)
return result;
+
+ requestInfo.resetChanged();
}
} else
m_profileIOData->releaseInterceptor();
@@ -262,17 +291,16 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
if (!resourceInfo)
return net::OK;
- int frameTreeNodeId = resourceInfo->GetFrameTreeNodeId();
- // Only intercept MAIN_FRAME and SUB_FRAME with an associated render frame.
- if (!content::IsResourceTypeFrame(resourceType) || frameTreeNodeId == -1)
+ if (!m_profileIOData->hasPageInterceptors() && !content::IsResourceTypeFrame(resourceType))
return net::OK;
+ auto webContentsGetter = resourceInfo->GetWebContentsGetterForRequest();
new URLRequestNotification(
request,
- qUrl,
resourceInfo->IsMainFrame(),
- navigationType,
- frameTreeNodeId,
+ newUrl,
+ std::move(requestInfo),
+ webContentsGetter,
std::move(callback)
);
@@ -290,13 +318,18 @@ void NetworkDelegateQt::OnCompleted(net::URLRequest */*request*/, bool /*started
bool NetworkDelegateQt::OnCanSetCookie(const net::URLRequest& request,
const net::CanonicalCookie & /*cookie*/,
- net::CookieOptions*)
+ net::CookieOptions*,
+ bool allowedFromCaller)
{
+ if (!allowedFromCaller)
+ return false;
return canSetCookies(request.site_for_cookies(), request.url(), std::string());
}
-bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest& request, const net::CookieList&)
+bool NetworkDelegateQt::OnCanGetCookies(const net::URLRequest& request, const net::CookieList&, bool allowedFromCaller)
{
+ if (!allowedFromCaller)
+ return false;
return canGetCookies(request.site_for_cookies(), request.url());
}
diff --git a/src/core/net/network_delegate_qt.h b/src/core/net/network_delegate_qt.h
index e4ff196aa..842af5006 100644
--- a/src/core/net/network_delegate_qt.h
+++ b/src/core/net/network_delegate_qt.h
@@ -62,7 +62,7 @@ public:
// net::NetworkDelegate implementation
int OnBeforeURLRequest(net::URLRequest* request, net::CompletionOnceCallback callback, GURL* new_url) override;
void OnURLRequestDestroyed(net::URLRequest* request) override;
- bool OnCanSetCookie(const net::URLRequest& request, const net::CanonicalCookie& cookie, net::CookieOptions* options) override;
+ bool OnCanSetCookie(const net::URLRequest& request, const net::CanonicalCookie& cookie, net::CookieOptions* options, bool) override;
int OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionOnceCallback callback, net::HttpRequestHeaders *headers) override;
void OnBeforeSendHeaders(net::URLRequest* request, const net::ProxyInfo& proxy_info,
const net::ProxyRetryInfoMap& proxy_retry_info, net::HttpRequestHeaders* headers) override;
@@ -75,7 +75,7 @@ public:
void OnCompleted(net::URLRequest *request, bool started, int net_error) override;
void OnPACScriptError(int, const base::string16&) override;
net::NetworkDelegate::AuthRequiredResponse OnAuthRequired(net::URLRequest*, const net::AuthChallengeInfo&, AuthCallback, net::AuthCredentials*) override;
- bool OnCanGetCookies(const net::URLRequest&, const net::CookieList&) override;
+ bool OnCanGetCookies(const net::URLRequest&, const net::CookieList&, bool) override;
bool OnCanAccessFile(const net::URLRequest&, const base::FilePath&, const base::FilePath&) const override;
bool OnCanEnablePrivacyMode(const GURL&, const GURL&) const override;
bool OnAreExperimentalCookieFeaturesEnabled() const override;
diff --git a/src/core/net/proxy_config_service_qt.h b/src/core/net/proxy_config_service_qt.h
index dcd303894..961927b89 100644
--- a/src/core/net/proxy_config_service_qt.h
+++ b/src/core/net/proxy_config_service_qt.h
@@ -76,7 +76,7 @@ private:
void RegisterObserver();
std::unique_ptr<net::ProxyConfigService> m_baseService;
- base::ObserverList<net::ProxyConfigService::Observer, true> m_observers;
+ base::ObserverList<net::ProxyConfigService::Observer, true>::Unchecked m_observers;
// Keep the last state around.
bool m_usesSystemConfiguration;
diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp
new file mode 100644
index 000000000..74a77a7ec
--- /dev/null
+++ b/src/core/net/qrc_url_scheme_handler.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qrc_url_scheme_handler.h"
+
+#include <QtWebEngineCore/qwebengineurlrequestjob.h>
+
+#include <QFile>
+#include <QFileInfo>
+#include <QMimeDatabase>
+#include <QMimeType>
+
+namespace QtWebEngineCore {
+
+void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job)
+{
+ QByteArray requestMethod = job->requestMethod();
+ if (requestMethod != "GET") {
+ job->fail(QWebEngineUrlRequestJob::RequestDenied);
+ return;
+ }
+
+ QUrl requestUrl = job->requestUrl();
+ QString requestPath = requestUrl.path();
+ QScopedPointer<QFile> file(new QFile(':' + requestPath, job));
+ QFileInfo fileInfo(*file);
+ QMimeDatabase mimeDatabase;
+ QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo);
+ job->reply(mimeType.name().toUtf8(), file.take());
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/net/qrc_url_scheme_handler.h b/src/core/net/qrc_url_scheme_handler.h
new file mode 100644
index 000000000..f6ca92879
--- /dev/null
+++ b/src/core/net/qrc_url_scheme_handler.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRC_URL_SCHEME_HANDLER_H
+#define QRC_URL_SCHEME_HANDLER_H
+
+#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
+#include <QtWebEngineCore/qwebengineurlschemehandler.h>
+
+namespace QtWebEngineCore {
+
+class QrcUrlSchemeHandler final : public QWebEngineUrlSchemeHandler {
+public:
+ void requestStarted(QWebEngineUrlRequestJob *) override;
+};
+
+} // namespace QtWebEngineCore
+
+#endif // !QRC_URL_SCHEME_HANDLER_H
diff --git a/src/core/net/url_request_context_getter_qt.cpp b/src/core/net/url_request_context_getter_qt.cpp
index 636d27358..6081a5e9f 100644
--- a/src/core/net/url_request_context_getter_qt.cpp
+++ b/src/core/net/url_request_context_getter_qt.cpp
@@ -40,6 +40,10 @@
#include "url_request_context_getter_qt.h"
#include "profile_io_data_qt.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+
namespace QtWebEngineCore {
URLRequestContextGetterQt::URLRequestContextGetterQt(ProfileIODataQt *data)
@@ -59,7 +63,7 @@ net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext()
scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const
{
- return content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO);
+ return base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO});
}
} // namespace QtWebEngineCore
diff --git a/src/core/net/url_request_custom_job.cpp b/src/core/net/url_request_custom_job.cpp
index d371c7bff..cba9b4dc5 100644
--- a/src/core/net/url_request_custom_job.cpp
+++ b/src/core/net/url_request_custom_job.cpp
@@ -39,6 +39,9 @@
#include "url_request_custom_job.h"
#include "url_request_custom_job_proxy.h"
+
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
@@ -68,17 +71,30 @@ URLRequestCustomJob::~URLRequestCustomJob()
if (m_device && m_device->isOpen())
m_device->close();
m_device = nullptr;
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::release,
- m_proxy));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&URLRequestCustomJobProxy::release, m_proxy));
}
void URLRequestCustomJob::Start()
{
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::initialize,
- m_proxy, request()->url(), request()->method(), request()->initiator()));
+ HttpRequestHeaders requestHeaders = request()->extra_request_headers();
+ std::map<std::string, std::string> headers;
+ net::HttpRequestHeaders::Iterator it(requestHeaders);
+ while (it.GetNext())
+ headers.emplace(it.name(), it.value());
+ if (!request()->referrer().empty())
+ headers.emplace("Referer", request()->referrer());
+
+ // TODO: handle UploadDataStream, for instance using a QIODevice wrapper.
+
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&URLRequestCustomJobProxy::initialize,
+ m_proxy,
+ request()->url(),
+ request()->method(),
+ request()->initiator(),
+ std::move(headers)));
}
void URLRequestCustomJob::Kill()
@@ -94,9 +110,9 @@ void URLRequestCustomJob::Kill()
m_pendingReadPos = 0;
}
m_device = nullptr;
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::release,
- m_proxy));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&URLRequestCustomJobProxy::release,
+ m_proxy));
URLRequestJob::Kill();
}
diff --git a/src/core/net/url_request_custom_job_delegate.cpp b/src/core/net/url_request_custom_job_delegate.cpp
index 338bd7137..83d47e291 100644
--- a/src/core/net/url_request_custom_job_delegate.cpp
+++ b/src/core/net/url_request_custom_job_delegate.cpp
@@ -40,9 +40,12 @@
#include "url_request_custom_job_delegate.h"
#include "url_request_custom_job_proxy.h"
-#include "type_conversion.h"
-#include "net/base/net_errors.h"
+#include "base/task/post_task.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "net/base/net_errors.h"
+
+#include "type_conversion.h"
#include <QByteArray>
@@ -51,11 +54,13 @@ namespace QtWebEngineCore {
URLRequestCustomJobDelegate::URLRequestCustomJobDelegate(URLRequestCustomJobProxy *proxy,
const QUrl &url,
const QByteArray &method,
- const QUrl &initiatorOrigin)
+ const QUrl &initiatorOrigin,
+ const QMap<QByteArray, QByteArray> &headers)
: m_proxy(proxy),
m_request(url),
m_method(method),
- m_initiatorOrigin(initiatorOrigin)
+ m_initiatorOrigin(initiatorOrigin),
+ m_requestHeaders(headers)
{
}
@@ -78,32 +83,36 @@ QUrl URLRequestCustomJobDelegate::initiator() const
return m_initiatorOrigin;
}
+const QMap<QByteArray, QByteArray> &URLRequestCustomJobDelegate::requestHeaders() const
+{
+ return m_requestHeaders;
+}
+
void URLRequestCustomJobDelegate::reply(const QByteArray &contentType, QIODevice *device)
{
if (device)
QObject::connect(device, &QIODevice::readyRead, this, &URLRequestCustomJobDelegate::slotReadyRead);
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::reply,
- m_proxy,contentType.toStdString(),device));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&URLRequestCustomJobProxy::reply,
+ m_proxy,contentType.toStdString(),device));
}
void URLRequestCustomJobDelegate::slotReadyRead()
{
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::readyRead, m_proxy));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&URLRequestCustomJobProxy::readyRead, m_proxy));
}
void URLRequestCustomJobDelegate::abort()
{
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::abort, m_proxy));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&URLRequestCustomJobProxy::abort, m_proxy));
}
void URLRequestCustomJobDelegate::redirect(const QUrl &url)
{
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::redirect,
- m_proxy, toGurl(url)));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&URLRequestCustomJobProxy::redirect, m_proxy, toGurl(url)));
}
void URLRequestCustomJobDelegate::fail(Error error)
@@ -129,9 +138,8 @@ void URLRequestCustomJobDelegate::fail(Error error)
break;
}
if (net_error) {
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::fail,
- m_proxy, net_error));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&URLRequestCustomJobProxy::fail, m_proxy, net_error));
}
}
diff --git a/src/core/net/url_request_custom_job_delegate.h b/src/core/net/url_request_custom_job_delegate.h
index caabfcf99..9de0224f9 100644
--- a/src/core/net/url_request_custom_job_delegate.h
+++ b/src/core/net/url_request_custom_job_delegate.h
@@ -54,6 +54,7 @@
#include "base/memory/ref_counted.h"
#include "qtwebenginecoreglobal_p.h"
+#include <QMap>
#include <QObject>
#include <QUrl>
@@ -80,6 +81,7 @@ public:
QUrl url() const;
QByteArray method() const;
QUrl initiator() const;
+ const QMap<QByteArray, QByteArray> &requestHeaders() const;
void reply(const QByteArray &contentType, QIODevice *device);
void redirect(const QUrl& url);
@@ -93,13 +95,15 @@ private:
URLRequestCustomJobDelegate(URLRequestCustomJobProxy *proxy,
const QUrl &url,
const QByteArray &method,
- const QUrl &initiatorOrigin);
+ const QUrl &initiatorOrigin,
+ const QMap<QByteArray, QByteArray> &requestHeaders);
friend class URLRequestCustomJobProxy;
scoped_refptr<URLRequestCustomJobProxy> m_proxy;
QUrl m_request;
QByteArray m_method;
QUrl m_initiatorOrigin;
+ const QMap<QByteArray, QByteArray> m_requestHeaders;
};
} // namespace
diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp
index b5f10388c..72d14450e 100644
--- a/src/core/net/url_request_custom_job_proxy.cpp
+++ b/src/core/net/url_request_custom_job_proxy.cpp
@@ -152,7 +152,9 @@ void URLRequestCustomJobProxy::readyRead()
m_job->notifyReadyRead();
}
-void URLRequestCustomJobProxy::initialize(GURL url, std::string method, base::Optional<url::Origin> initiator)
+void URLRequestCustomJobProxy::initialize(GURL url, std::string method,
+ base::Optional<url::Origin> initiator,
+ std::map<std::string, std::string> headers)
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
Q_ASSERT(!m_delegate);
@@ -164,12 +166,16 @@ void URLRequestCustomJobProxy::initialize(GURL url, std::string method, base::Op
QWebEngineUrlSchemeHandler *schemeHandler = nullptr;
if (m_profileAdapter)
- schemeHandler = m_profileAdapter->customUrlSchemeHandlers()[toQByteArray(m_scheme)];
+ schemeHandler = m_profileAdapter->urlSchemeHandler(toQByteArray(m_scheme));
+ QMap<QByteArray, QByteArray> qHeaders;
+ for (auto it = headers.cbegin(); it != headers.cend(); ++it)
+ qHeaders.insert(toQByteArray(it->first), toQByteArray(it->second));
if (schemeHandler) {
m_delegate = new URLRequestCustomJobDelegate(this, toQt(url),
QByteArray::fromStdString(method),
- initiatorOrigin);
+ initiatorOrigin,
+ qHeaders);
QWebEngineUrlRequestJob *requestJob = new QWebEngineUrlRequestJob(m_delegate);
schemeHandler->requestStarted(requestJob);
}
diff --git a/src/core/net/url_request_custom_job_proxy.h b/src/core/net/url_request_custom_job_proxy.h
index 3986fe119..aa55db07c 100644
--- a/src/core/net/url_request_custom_job_proxy.h
+++ b/src/core/net/url_request_custom_job_proxy.h
@@ -72,7 +72,7 @@ public:
void abort();
void fail(int error);
void release();
- void initialize(GURL url, std::string method, base::Optional<url::Origin> initiatorOrigin);
+ void initialize(GURL url, std::string method, base::Optional<url::Origin> initiatorOrigin, std::map<std::string, std::string> headers);
void readyRead();
// IO thread owned:
diff --git a/src/core/net/url_request_qrc_job_qt.cpp b/src/core/net/url_request_qrc_job_qt.cpp
deleted file mode 100644
index a2712653d..000000000
--- a/src/core/net/url_request_qrc_job_qt.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/****************************************************************************
-**
-** 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:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** 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-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "url_request_qrc_job_qt.h"
-
-#include "type_conversion.h"
-
-#include "base/pending_task.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "net/base/net_errors.h"
-#include "net/base/io_buffer.h"
-
-#include <QUrl>
-#include <QFileInfo>
-#include <QMimeDatabase>
-#include <QMimeType>
-
-using namespace net;
-namespace QtWebEngineCore {
-
-URLRequestQrcJobQt::URLRequestQrcJobQt(URLRequest *request, NetworkDelegate *networkDelegate)
- : URLRequestJob(request, networkDelegate)
- , m_remainingBytes(0)
- , m_weakFactory(this)
-{
-}
-
-URLRequestQrcJobQt::~URLRequestQrcJobQt()
-{
- if (m_file.isOpen())
- m_file.close();
-}
-
-void URLRequestQrcJobQt::Start()
-{
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&URLRequestQrcJobQt::startGetHead, m_weakFactory.GetWeakPtr()));
-}
-
-void URLRequestQrcJobQt::Kill()
-{
- if (m_file.isOpen())
- m_file.close();
- m_weakFactory.InvalidateWeakPtrs();
-
- URLRequestJob::Kill();
-}
-
-bool URLRequestQrcJobQt::GetMimeType(std::string *mimeType) const
-{
- DCHECK(request_);
- if (m_mimeType.size() > 0) {
- *mimeType = m_mimeType;
- return true;
- }
- return false;
-}
-
-int URLRequestQrcJobQt::ReadRawData(IOBuffer *buf, int bufSize)
-{
- DCHECK_GE(m_remainingBytes, 0);
- // File has been read finished.
- if (!m_remainingBytes || !bufSize) {
- return 0;
- }
- if (m_remainingBytes < bufSize)
- bufSize = static_cast<int>(m_remainingBytes);
- qint64 rv = m_file.read(buf->data(), bufSize);
- if (rv >= 0) {
- m_remainingBytes -= rv;
- DCHECK_GE(m_remainingBytes, 0);
- return static_cast<int>(rv);
- }
- return static_cast<int>(rv);
-}
-
-void URLRequestQrcJobQt::startGetHead()
-{
- // Get qrc file path.
- QString qrcFilePath = ':' + toQt(request_->url()).path();
- m_file.setFileName(qrcFilePath);
- QFileInfo qrcFileInfo(m_file);
- // Get qrc file mime type.
- QMimeDatabase mimeDatabase;
- QMimeType mimeType = mimeDatabase.mimeTypeForFile(qrcFileInfo);
- m_mimeType = mimeType.name().toStdString();
- // Open file
- if (m_file.open(QIODevice::ReadOnly)) {
- m_remainingBytes = m_file.size();
- set_expected_content_size(m_remainingBytes);
- // Notify that the headers are complete
- NotifyHeadersComplete();
- } else {
- NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, ERR_INVALID_URL));
- }
-}
-
-} // namespace QtWebEngineCore
diff --git a/src/core/net/webui_controller_factory_qt.cpp b/src/core/net/webui_controller_factory_qt.cpp
index 918500b58..ec36e70d9 100644
--- a/src/core/net/webui_controller_factory_qt.cpp
+++ b/src/core/net/webui_controller_factory_qt.cpp
@@ -48,6 +48,7 @@
#include "base/location.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "chrome/browser/accessibility/accessibility_ui.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/devtools_ui.h"
#include "chrome/browser/ui/webui/quota_internals/quota_internals_ui.h"
@@ -136,6 +137,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, co
// return nullptr;
return &NewWebUI<DevToolsUI>;
}
+ if (url.host() == chrome::kChromeUIAccessibilityHost)
+ return &NewWebUI<AccessibilityUI>;
// if (url.host_piece() == chrome::kChromeUIUserActionsHost)
// return &NewWebUI<UserActionsUI>;
diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp
index ec49414b0..7e913817e 100644
--- a/src/core/ozone/gl_context_qt.cpp
+++ b/src/core/ozone/gl_context_qt.cpp
@@ -119,7 +119,13 @@ void* GLContextHelper::getGlXConfig()
void* GLContextHelper::getEGLDisplay()
{
+#ifdef Q_OS_WIN
+ // Windows QPA plugin does not implement resourceForIntegration for "egldisplay".
+ // Use resourceForContext instead.
+ return resourceForContext(QByteArrayLiteral("egldisplay"));
+#else
return resourceForIntegration(QByteArrayLiteral("egldisplay"));
+#endif
}
void* GLContextHelper::getXDisplay()
diff --git a/src/core/ozone/gl_surface_egl_qt.cpp b/src/core/ozone/gl_surface_egl_qt.cpp
index 9fe5985ce..8715a5095 100644
--- a/src/core/ozone/gl_surface_egl_qt.cpp
+++ b/src/core/ozone/gl_surface_egl_qt.cpp
@@ -44,9 +44,9 @@
#include "gl_context_qt.h"
#include "ozone/gl_surface_egl_qt.h"
-#include "ui/gl/gl_surface_egl.h"
#if !defined(OS_MACOSX)
#include "ui/gl/egl_util.h"
+#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/init/gl_factory.h"
// From ANGLE's egl/eglext.h.
@@ -302,10 +302,6 @@ void* GLSurfacelessQtEGL::GetShareHandle()
return NULL;
}
-} // namespace gl
-#endif // !defined(OS_MACOSX)
-
-namespace gl {
std::string DriverEGL::GetPlatformExtensions()
{
EGLDisplay display = GLContextHelper::getEGLDisplay();
@@ -317,3 +313,15 @@ std::string DriverEGL::GetPlatformExtensions()
return str ? std::string(str) : "";
}
} // namespace gl
+#else
+namespace gl {
+struct GL_EXPORT DriverEGL {
+ static std::string GetPlatformExtensions();
+};
+
+std::string DriverEGL::GetPlatformExtensions()
+{
+ return "";
+}
+} // namespace gl
+#endif // !defined(OS_MACOSX)
diff --git a/src/core/ozone/gl_surface_qt.cpp b/src/core/ozone/gl_surface_qt.cpp
index 7cde289ae..551ba888c 100644
--- a/src/core/ozone/gl_surface_qt.cpp
+++ b/src/core/ozone/gl_surface_qt.cpp
@@ -64,7 +64,6 @@
#include "ozone/gl_surface_wgl_qt.h"
#include "gpu/ipc/service/direct_composition_surface_win.h"
-#include "ui/gl/gl_context_wgl.h"
#include "ui/gl/vsync_provider_win.h"
#endif
@@ -141,9 +140,6 @@ bool InitializeGLOneOffPlatform()
{
VSyncProviderWin::InitializeOneOff();
- if (GetGLImplementation() == kGLImplementationOSMesaGL)
- return false;
-
if (GetGLImplementation() == kGLImplementationEGLGLES2)
return GLSurfaceEGLQt::InitializeOneOff();
diff --git a/src/core/ozone/gl_surface_wgl_qt.cpp b/src/core/ozone/gl_surface_wgl_qt.cpp
index 7c9e87b86..ac27a9c20 100644
--- a/src/core/ozone/gl_surface_wgl_qt.cpp
+++ b/src/core/ozone/gl_surface_wgl_qt.cpp
@@ -37,9 +37,9 @@
**
****************************************************************************/
-#if defined(OS_WIN)
-
#include "gl_surface_wgl_qt.h"
+
+#if defined(OS_WIN)
#include "ui/gl/gl_surface_wgl.h"
namespace gl {
diff --git a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp
index 905e8f403..1115f3fac 100644
--- a/src/core/ozone/ozone_platform_qt.cpp
+++ b/src/core/ozone/ozone_platform_qt.cpp
@@ -43,6 +43,7 @@
#include "ozone/surface_factory_qt.h"
#include "ozone/platform_window_qt.h"
#include "ui/display/types/native_display_delegate.h"
+#include "ui/events/system_input_injector.h"
#include "ui/ozone/common/stub_client_native_pixmap_factory.h"
#include "ui/ozone/common/stub_overlay_manager.h"
#include "ui/ozone/public/cursor_factory_ozone.h"
diff --git a/src/core/ozone/platform_window_qt.h b/src/core/ozone/platform_window_qt.h
index b712b706a..bb2fc714b 100644
--- a/src/core/ozone/platform_window_qt.h
+++ b/src/core/ozone/platform_window_qt.h
@@ -75,6 +75,9 @@ public:
void MoveCursorTo(const gfx::Point&) override { }
void ConfineCursorToBounds(const gfx::Rect&) override { }
PlatformImeController* GetPlatformImeController() override { return nullptr; }
+ void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override { }
+ gfx::Rect GetRestoredBoundsInPixels() const override { return gfx::Rect(); }
+
// PlatformEventDispatcher:
bool CanDispatchEvent(const PlatformEvent& event) override;
uint32_t DispatchEvent(const PlatformEvent& event) override;
diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp
index b999f4186..cf3041e7a 100644
--- a/src/core/permission_manager_qt.cpp
+++ b/src/core/permission_manager_qt.cpp
@@ -76,6 +76,7 @@ ProfileAdapter::PermissionType toQt(content::PermissionType type)
case content::PermissionType::CLIPBOARD_WRITE:
return ProfileAdapter::ClipboardWrite;
case content::PermissionType::PAYMENT_HANDLER:
+ case content::PermissionType::BACKGROUND_FETCH:
case content::PermissionType::NUM:
break;
}
@@ -294,8 +295,8 @@ void PermissionManagerQt::ResetPermission(
int PermissionManagerQt::SubscribePermissionStatusChange(
content::PermissionType permission,
+ content::RenderFrameHost * /* render_frame_host */,
const GURL& requesting_origin,
- const GURL& /*embedding_origin*/,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
{
int subscriber_id = ++m_subscriberIdCount;
@@ -311,7 +312,7 @@ int PermissionManagerQt::SubscribePermissionStatusChange(
void PermissionManagerQt::UnsubscribePermissionStatusChange(int subscription_id)
{
if (!m_subscribers.remove(subscription_id))
- qWarning() << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id;
+ LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id;
}
} // namespace QtWebEngineCore
diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h
index b3bd3dc7a..89eb6cf85 100644
--- a/src/core/permission_manager_qt.h
+++ b/src/core/permission_manager_qt.h
@@ -92,8 +92,8 @@ public:
int SubscribePermissionStatusChange(
content::PermissionType permission,
+ content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- const GURL& embedding_origin,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override;
void UnsubscribePermissionStatusChange(int subscription_id) override;
diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp
index 0e7239ef8..1a16be69e 100644
--- a/src/core/printing/print_view_manager_base_qt.cpp
+++ b/src/core/printing/print_view_manager_base_qt.cpp
@@ -52,6 +52,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/post_task.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -59,12 +60,13 @@
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/printer_query.h"
#include "components/printing/common/print_messages.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
-#include "printing/pdf_metafile_skia.h"
+#include "printing/metafile_skia.h"
#include "printing/print_job_constants.h"
#include "printing/printed_document.h"
@@ -123,8 +125,8 @@ void PrintViewManagerBaseQt::PrintDocument(printing::PrintedDocument *document,
const gfx::Rect &content_area,
const gfx::Point &offsets)
{
- std::unique_ptr<printing::PdfMetafileSkia> metafile =
- std::make_unique<printing::PdfMetafileSkia>();
+ std::unique_ptr<printing::MetafileSkia> metafile =
+ std::make_unique<printing::MetafileSkia>();
CHECK(metafile->InitFromData(print_data->front(), print_data->size()));
// Update the rendered document. It will send notifications to the listener.
@@ -155,21 +157,19 @@ void PrintViewManagerBaseQt::OnDidPrintDocument(content::RenderFrameHost* /*rend
return;
const PrintHostMsg_DidPrintContent_Params &content = params.content;
- if (!base::SharedMemory::IsHandleValid(content.metafile_data_handle)) {
+ if (!content.metafile_data_region.IsValid()) {
NOTREACHED() << "invalid memory handle";
web_contents()->Stop();
return;
}
- std::unique_ptr<base::SharedMemory> shared_buf =
- std::make_unique<base::SharedMemory>(content.metafile_data_handle, true);
- if (!shared_buf->Map(content.data_size)) {
+ auto data = base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(content.metafile_data_region);
+ if (!data) {
NOTREACHED() << "couldn't map";
web_contents()->Stop();
return;
}
- auto data = base::MakeRefCounted<base::RefCountedSharedMemory>(
- std::move(shared_buf), content.data_size);
+
PrintDocument(document, data, params.page_size, params.content_area,
params.physical_offsets);
}
@@ -516,9 +516,8 @@ void PrintViewManagerBaseQt::ReleasePrinterQuery()
printerQuery = m_printerQueriesQueue->PopPrinterQuery(cookie);
if (!printerQuery.get())
return;
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::BindOnce(&printing::PrinterQuery::StopWorker, printerQuery.get()));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&printing::PrinterQuery::StopWorker, printerQuery.get()));
}
// Originally from print_preview_message_handler.cc:
@@ -528,7 +527,7 @@ void PrintViewManagerBaseQt::StopWorker(int documentCookie) {
scoped_refptr<printing::PrinterQuery> printer_query =
m_printerQueriesQueue->PopPrinterQuery(documentCookie);
if (printer_query.get()) {
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&printing::PrinterQuery::StopWorker, printer_query));
}
}
diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp
index ff9fc76be..e88f48624 100644
--- a/src/core/printing/print_view_manager_qt.cpp
+++ b/src/core/printing/print_view_manager_qt.cpp
@@ -53,50 +53,43 @@
#include "base/values.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/printer_query.h"
#include "components/printing/common/print_messages.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/web_preferences.h"
-#include "printing/pdf_metafile_skia.h"
+#include "printing/metafile_skia.h"
#include "printing/print_job_constants.h"
#include "printing/units.h"
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(QtWebEngineCore::PrintViewManagerQt);
-
namespace {
static const qreal kMicronsToMillimeter = 1000.0f;
-static std::vector<char>
-GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size)
+static QSharedPointer<QByteArray> GetStdVectorFromHandle(const base::ReadOnlySharedMemoryRegion &handle)
{
- std::unique_ptr<base::SharedMemory> shared_buf(
- new base::SharedMemory(handle, true));
-
- if (!shared_buf->Map(data_size)) {
- return std::vector<char>();
- }
+ base::ReadOnlySharedMemoryMapping map = handle.Map();
+ if (!map.IsValid())
+ return QSharedPointer<QByteArray>(new QByteArray);
- char* data = static_cast<char*>(shared_buf->memory());
- return std::vector<char>(data, data + data_size);
+ const char* data = static_cast<const char*>(map.memory());
+ return QSharedPointer<QByteArray>(new QByteArray(data, map.size()));
}
static scoped_refptr<base::RefCountedBytes>
-GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size)
+GetBytesFromHandle(const base::ReadOnlySharedMemoryRegion &handle)
{
- std::unique_ptr<base::SharedMemory> shared_buf(new base::SharedMemory(handle, true));
-
- if (!shared_buf->Map(data_size)) {
+ base::ReadOnlySharedMemoryMapping map = handle.Map();
+ if (!map.IsValid())
return nullptr;
- }
- unsigned char* data = static_cast<unsigned char*>(shared_buf->memory());
- std::vector<unsigned char> dataVector(data, data + data_size);
+ const unsigned char* data = static_cast<const unsigned char*>(map.memory());
+ std::vector<unsigned char> dataVector(data, data + map.size());
return base::RefCountedBytes::TakeVector(&dataVector);
}
@@ -108,15 +101,14 @@ static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data,
base::AssertBlockingAllowed();
DCHECK_GT(data->size(), 0U);
- printing::PdfMetafileSkia metafile;
+ printing::MetafileSkia metafile;
metafile.InitFromData(static_cast<const void*>(data->front()), data->size());
base::File file(path,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
bool success = file.IsValid() && metafile.SaveTo(&file);
- content::BrowserThread::PostTask(content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(saveCallback, success));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(saveCallback, success));
}
static base::DictionaryValue *createPrintSettings()
@@ -222,16 +214,16 @@ void PrintViewManagerQt::PrintToPDFFileWithCallback(const QPageLayout &pageLayou
return;
if (m_printSettings || !filePath.length()) {
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(callback, false));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(callback, false));
return;
}
m_pdfOutputPath = toFilePath(filePath);
m_pdfSaveCallback = callback;
if (!PrintToPDFInternal(pageLayout, printInColor)) {
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(callback, false));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(callback, false));
resetPdfState();
}
}
@@ -246,16 +238,15 @@ void PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout,
// If there already is a pending print in progress, don't try starting another one.
if (m_printSettings) {
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(callback, std::vector<char>()));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(callback, QSharedPointer<QByteArray>()));
return;
}
m_pdfPrintCallback = callback;
if (!PrintToPDFInternal(pageLayout, printInColor, useCustomMargins)) {
- content::BrowserThread::PostTask(content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(callback, std::vector<char>()));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(callback, QSharedPointer<QByteArray>()));
resetPdfState();
}
@@ -358,21 +349,18 @@ void PrintViewManagerQt::OnMetafileReadyForPrinting(content::RenderFrameHost* rf
StopWorker(params.document_cookie);
// Create local copies so we can reset the state and take a new pdf print job.
- base::Callback<void(const std::vector<char>&)> pdf_print_callback = m_pdfPrintCallback;
- base::Callback<void(bool)> pdf_save_callback = m_pdfSaveCallback;
+ PrintToPDFCallback pdf_print_callback = std::move(m_pdfPrintCallback);
+ PrintToPDFFileCallback pdf_save_callback = std::move(m_pdfSaveCallback);
base::FilePath pdfOutputPath = m_pdfOutputPath;
resetPdfState();
if (!pdf_print_callback.is_null()) {
- std::vector<char> data_vector = GetStdVectorFromHandle(params.content.metafile_data_handle,
- params.content.data_size);
- content::BrowserThread::PostTask(content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(pdf_print_callback, data_vector));
+ QSharedPointer<QByteArray> data_array = GetStdVectorFromHandle(params.content.metafile_data_region);
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(pdf_print_callback, data_array));
} else {
- scoped_refptr<base::RefCountedBytes> data_bytes
- = GetBytesFromHandle(params.content.metafile_data_handle, params.content.data_size);
+ scoped_refptr<base::RefCountedBytes> data_bytes = GetBytesFromHandle(params.content.metafile_data_region);
base::PostTaskWithTraits(FROM_HERE, {base::MayBlock()},
base::BindOnce(&SavePdfFile, data_bytes, pdfOutputPath, pdf_save_callback));
}
@@ -392,9 +380,8 @@ void PrintViewManagerQt::DidStartLoading()
void PrintViewManagerQt::NavigationStopped()
{
if (!m_pdfPrintCallback.is_null()) {
- content::BrowserThread::PostTask(content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(m_pdfPrintCallback, std::vector<char>()));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(m_pdfPrintCallback, QSharedPointer<QByteArray>()));
}
resetPdfState();
PrintViewManagerBaseQt::NavigationStopped();
@@ -404,9 +391,8 @@ void PrintViewManagerQt::RenderProcessGone(base::TerminationStatus status)
{
PrintViewManagerBaseQt::RenderProcessGone(status);
if (!m_pdfPrintCallback.is_null()) {
- content::BrowserThread::PostTask(content::BrowserThread::UI,
- FROM_HERE,
- base::Bind(m_pdfPrintCallback, std::vector<char>()));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(m_pdfPrintCallback, QSharedPointer<QByteArray>()));
}
resetPdfState();
}
diff --git a/src/core/printing/print_view_manager_qt.h b/src/core/printing/print_view_manager_qt.h
index 209be8782..b21389691 100644
--- a/src/core/printing/print_view_manager_qt.h
+++ b/src/core/printing/print_view_manager_qt.h
@@ -56,6 +56,8 @@
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/web_contents_user_data.h"
+#include <QSharedPointer>
+
struct PrintHostMsg_RequestPrintPreview_Params;
struct PrintHostMsg_DidPreviewDocument_Params;
@@ -83,7 +85,7 @@ class PrintViewManagerQt
{
public:
~PrintViewManagerQt() override;
- typedef base::Callback<void(const std::vector<char> &result)> PrintToPDFCallback;
+ typedef base::Callback<void(QSharedPointer<QByteArray> result)> PrintToPDFCallback;
typedef base::Callback<void(bool success)> PrintToPDFFileCallback;
// Method to print a page to a Pdf document with page size \a pageSize in location \a filePath.
diff --git a/src/core/process_main.cpp b/src/core/process_main.cpp
index 677f0b10a..d661d3b90 100644
--- a/src/core/process_main.cpp
+++ b/src/core/process_main.cpp
@@ -44,7 +44,10 @@
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox_types.h"
#include "content/public/app/sandbox_helper_win.h"
-#endif // OS_WIN
+#elif defined(OS_MACOSX)
+#include "base/logging.h"
+#include "sandbox/mac/seatbelt_exec.h"
+#endif
namespace QtWebEngine {
@@ -64,6 +67,13 @@ int processMain(int argc, const char **argv)
params.argc = argc;
params.argv = argv;
#endif // OS_WIN
+#if defined(OS_MACOSX)
+ sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt =
+ sandbox::SeatbeltExecServer::CreateFromArguments(argv[0], argc, const_cast<char**>(argv));
+ if (seatbelt.sandbox_required) {
+ CHECK(seatbelt.server->InitializeSandbox());
+ }
+#endif // defined(OS_MACOSX)
return content::ContentMain(params);
}
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 462be9f48..dfe701cc9 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -44,10 +44,12 @@
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/download_manager.h"
+#include "api/qwebengineurlscheme.h"
#include "content_client_qt.h"
#include "download_manager_delegate_qt.h"
#include "net/url_request_context_getter_qt.h"
#include "permission_manager_qt.h"
+#include "profile_adapter_client.h"
#include "profile_qt.h"
#include "renderer_host/user_resource_controller_host.h"
#include "type_conversion.h"
@@ -81,6 +83,8 @@ ProfileAdapter::ProfileAdapter(const QString &storageName):
, m_persistentCookiesPolicy(AllowPersistentCookies)
, m_visitedLinksPolicy(TrackVisitedLinksOnDisk)
, m_httpCacheMaxSize(0)
+ , m_pageRequestInterceptors(0)
+ , m_downloadPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))
{
WebEngineContext::current()->addProfileAdapter(this);
// creation of profile requires webengine context
@@ -88,6 +92,7 @@ ProfileAdapter::ProfileAdapter(const QString &storageName):
content::BrowserContext::Initialize(m_profile.data(), toFilePath(dataPath()));
// fixme: this should not be here
m_profile->m_profileIOData->initializeOnUIThread();
+ m_customUrlSchemeHandlers.insert(QByteArrayLiteral("qrc"), &m_qrcHandler);
}
ProfileAdapter::~ProfileAdapter()
@@ -97,6 +102,7 @@ ProfileAdapter::~ProfileAdapter()
m_profile->GetDownloadManager(m_profile.data())->Shutdown();
m_downloadManagerDelegate.reset();
}
+ Q_ASSERT(m_pageRequestInterceptors == 0);
}
void ProfileAdapter::setStorageName(const QString &storageName)
@@ -173,6 +179,22 @@ void ProfileAdapter::removeClient(ProfileAdapterClient *adapterClient)
m_clients.removeOne(adapterClient);
}
+void ProfileAdapter::addPageRequestInterceptor()
+{
+ ++m_pageRequestInterceptors;
+ if (m_profile->m_urlRequestContextGetter.get())
+ m_profile->m_profileIOData->updateRequestInterceptor();
+}
+
+void ProfileAdapter::removePageRequestInterceptor()
+{
+ Q_ASSERT(m_pageRequestInterceptors > 0);
+ --m_pageRequestInterceptors;
+ if (m_profile->m_urlRequestContextGetter.get())
+ m_profile->m_profileIOData->updateRequestInterceptor();
+}
+
+
void ProfileAdapter::cancelDownload(quint32 downloadId)
{
downloadManagerDelegate()->cancelDownload(downloadId);
@@ -232,6 +254,11 @@ void ProfileAdapter::setDataPath(const QString &path)
}
}
+void ProfileAdapter::setDownloadPath(const QString &path)
+{
+ m_downloadPath = path.isEmpty() ? QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) : path;
+}
+
QString ProfileAdapter::cachePath() const
{
if (m_offTheRecord)
@@ -400,9 +427,23 @@ void ProfileAdapter::setHttpCacheMaxSize(int maxSize)
m_profile->m_profileIOData->updateHttpCache();
}
-const QHash<QByteArray, QWebEngineUrlSchemeHandler *> &ProfileAdapter::customUrlSchemeHandlers() const
+static bool isInternalScheme(const QByteArray &scheme)
{
- return m_customUrlSchemeHandlers;
+ static QSet<QByteArray> internalSchemes{
+ QByteArrayLiteral("qrc"),
+ QByteArrayLiteral("data"),
+ QByteArrayLiteral("blob"),
+ QByteArrayLiteral("http"),
+ QByteArrayLiteral("https"),
+ QByteArrayLiteral("ftp"),
+ QByteArrayLiteral("javascript"),
+ };
+ return internalSchemes.contains(scheme);
+}
+
+QWebEngineUrlSchemeHandler *ProfileAdapter::urlSchemeHandler(const QByteArray &scheme)
+{
+ return m_customUrlSchemeHandlers.value(scheme.toLower()).data();
}
const QList<QByteArray> ProfileAdapter::customUrlSchemes() const
@@ -416,12 +457,17 @@ void ProfileAdapter::updateCustomUrlSchemeHandlers()
m_profile->m_profileIOData->updateJobFactory();
}
-bool ProfileAdapter::removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler)
+void ProfileAdapter::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler)
{
+ Q_ASSERT(handler);
bool removedOneOrMore = false;
auto it = m_customUrlSchemeHandlers.begin();
while (it != m_customUrlSchemeHandlers.end()) {
if (it.value() == handler) {
+ if (isInternalScheme(it.key())) {
+ qWarning("Cannot remove the URL scheme handler for an internal scheme: %s", it.key().constData());
+ continue;
+ }
it = m_customUrlSchemeHandlers.erase(it);
removedOneOrMore = true;
continue;
@@ -430,26 +476,43 @@ bool ProfileAdapter::removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *ha
}
if (removedOneOrMore)
updateCustomUrlSchemeHandlers();
- return removedOneOrMore;
}
-QWebEngineUrlSchemeHandler *ProfileAdapter::takeCustomUrlSchemeHandler(const QByteArray &scheme)
+void ProfileAdapter::removeUrlScheme(const QByteArray &scheme)
{
- QWebEngineUrlSchemeHandler *handler = m_customUrlSchemeHandlers.take(scheme);
- if (handler)
+ QByteArray canonicalScheme = scheme.toLower();
+ if (isInternalScheme(canonicalScheme)) {
+ qWarning("Cannot remove the URL scheme handler for an internal scheme: %s", scheme.constData());
+ return;
+ }
+ if (m_customUrlSchemeHandlers.remove(canonicalScheme))
updateCustomUrlSchemeHandlers();
- return handler;
}
-void ProfileAdapter::addCustomUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler)
+void ProfileAdapter::installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler)
{
- m_customUrlSchemeHandlers.insert(scheme, handler);
+ Q_ASSERT(handler);
+ QByteArray canonicalScheme = scheme.toLower();
+ if (isInternalScheme(canonicalScheme)) {
+ qWarning("Cannot install a URL scheme handler overriding internal scheme: %s", scheme.constData());
+ return;
+ }
+ if (m_customUrlSchemeHandlers.value(canonicalScheme, handler) != handler) {
+ qWarning("URL scheme handler already installed for the scheme: %s", scheme.constData());
+ return;
+ }
+ if (QWebEngineUrlScheme::schemeByName(canonicalScheme) == QWebEngineUrlScheme())
+ qWarning("Please register the custom scheme '%s' via QWebEngineUrlScheme::registerScheme() "
+ "before installing the custom scheme handler.", scheme.constData());
+
+ m_customUrlSchemeHandlers.insert(canonicalScheme, handler);
updateCustomUrlSchemeHandlers();
}
-void ProfileAdapter::clearCustomUrlSchemeHandlers()
+void ProfileAdapter::removeAllUrlSchemeHandlers()
{
m_customUrlSchemeHandlers.clear();
+ m_customUrlSchemeHandlers.insert(QByteArrayLiteral("qrc"), &m_qrcHandler);
updateCustomUrlSchemeHandlers();
}
@@ -548,7 +611,37 @@ bool ProfileAdapter::isSpellCheckEnabled() const
void ProfileAdapter::resetVisitedLinksManager()
{
- m_visitedLinksManager.reset(new VisitedLinksManagerQt(this));
+ m_visitedLinksManager.reset(new VisitedLinksManagerQt(m_profile.data(), persistVisitedLinks()));
+}
+
+void ProfileAdapter::setUseForGlobalCertificateVerification(bool enable)
+{
+ if (m_usedForGlobalCertificateVerification == enable)
+ return;
+
+ static QPointer<ProfileAdapter> profileForglobalCertificateVerification;
+
+ m_usedForGlobalCertificateVerification = enable;
+ if (enable) {
+ if (profileForglobalCertificateVerification) {
+ profileForglobalCertificateVerification->m_usedForGlobalCertificateVerification = false;
+ for (auto *client : qAsConst(profileForglobalCertificateVerification->m_clients))
+ client->useForGlobalCertificateVerificationChanged();
+ }
+ profileForglobalCertificateVerification = this;
+ } else {
+ Q_ASSERT(profileForglobalCertificateVerification);
+ Q_ASSERT(profileForglobalCertificateVerification == this);
+ profileForglobalCertificateVerification = nullptr;
+ }
+
+ if (m_profile->m_urlRequestContextGetter.get())
+ m_profile->m_profileIOData->updateUsedForGlobalCertificateVerification();
+}
+
+bool ProfileAdapter::isUsedForGlobalCertificateVerification() const
+{
+ return m_usedForGlobalCertificateVerification;
}
} // namespace QtWebEngineCore
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index 9bc92b54a..800058bc5 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -63,6 +63,7 @@
#include "api/qwebenginecookiestore.h"
#include "api/qwebengineurlrequestinterceptor.h"
#include "api/qwebengineurlschemehandler.h"
+#include "net/qrc_url_scheme_handler.h"
QT_FORWARD_DECLARE_CLASS(QObject)
@@ -112,6 +113,9 @@ public:
QString dataPath() const;
void setDataPath(const QString &path);
+ QString downloadPath() const { return m_downloadPath; }
+ void setDownloadPath(const QString &path);
+
QString cachePath() const;
void setCachePath(const QString &path);
@@ -170,14 +174,14 @@ public:
void setHttpCacheMaxSize(int maxSize);
bool trackVisitedLinks() const;
- bool persistVisitedLinks() const;
- const QHash<QByteArray, QWebEngineUrlSchemeHandler *> &customUrlSchemeHandlers() const;
+ QWebEngineUrlSchemeHandler *urlSchemeHandler(const QByteArray &scheme);
+ void installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler);
+ void removeUrlScheme(const QByteArray &scheme);
+ void removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler);
+ void removeAllUrlSchemeHandlers();
+
const QList<QByteArray> customUrlSchemes() const;
- void clearCustomUrlSchemeHandlers();
- void addCustomUrlSchemeHandler(const QByteArray &, QWebEngineUrlSchemeHandler *);
- bool removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *);
- QWebEngineUrlSchemeHandler *takeCustomUrlSchemeHandler(const QByteArray &);
UserResourceControllerHost *userResourceController();
void permissionRequestReply(const QUrl &origin, PermissionType type, bool reply);
@@ -189,12 +193,21 @@ public:
void clearHttpCache();
+ void setUseForGlobalCertificateVerification(bool enable = true);
+ bool isUsedForGlobalCertificateVerification() const;
+
+ void addPageRequestInterceptor();
+ void removePageRequestInterceptor();
+ bool hasPageRequestInterceptor() const { return m_pageRequestInterceptors > 0; }
+
private:
void updateCustomUrlSchemeHandlers();
void resetVisitedLinksManager();
+ bool persistVisitedLinks() const;
QString m_name;
bool m_offTheRecord;
+ bool m_usedForGlobalCertificateVerification = false;
QScopedPointer<ProfileQt> m_profile;
QScopedPointer<VisitedLinksManagerQt> m_visitedLinksManager;
QScopedPointer<DownloadManagerDelegateQt> m_downloadManagerDelegate;
@@ -203,15 +216,18 @@ private:
QPointer<QWebEngineUrlRequestInterceptor> m_requestInterceptor;
QString m_dataPath;
+ QString m_downloadPath;
QString m_cachePath;
QString m_httpUserAgent;
HttpCacheType m_httpCacheType;
QString m_httpAcceptLanguage;
PersistentCookiesPolicy m_persistentCookiesPolicy;
VisitedLinksPolicy m_visitedLinksPolicy;
- QHash<QByteArray, QWebEngineUrlSchemeHandler *> m_customUrlSchemeHandlers;
+ QHash<QByteArray, QPointer<QWebEngineUrlSchemeHandler>> m_customUrlSchemeHandlers;
QList<ProfileAdapterClient*> m_clients;
int m_httpCacheMaxSize;
+ int m_pageRequestInterceptors;
+ QrcUrlSchemeHandler m_qrcHandler;
Q_DISABLE_COPY(ProfileAdapter)
};
diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h
index 06051fab6..4711f8bcf 100644
--- a/src/core/profile_adapter_client.h
+++ b/src/core/profile_adapter_client.h
@@ -142,6 +142,7 @@ public:
virtual void downloadRequested(DownloadItemInfo &info) = 0;
virtual void downloadUpdated(const DownloadItemInfo &info) = 0;
+ virtual void useForGlobalCertificateVerificationChanged() {}
static QString downloadInterruptReasonToString(DownloadInterruptReason reason);
};
diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp
index 7783f1ae7..20754ed7a 100644
--- a/src/core/profile_io_data_qt.cpp
+++ b/src/core/profile_io_data_qt.cpp
@@ -39,9 +39,10 @@
#include "profile_io_data_qt.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "components/certificate_transparency/ct_known_logs.h"
#include "components/network_session_configurator/common/network_features.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/cookie_store_factory.h"
@@ -80,12 +81,20 @@
#include "net/custom_protocol_handler.h"
#include "net/network_delegate_qt.h"
#include "net/proxy_config_service_qt.h"
-#include "net/qrc_protocol_handler_qt.h"
#include "net/url_request_context_getter_qt.h"
#include "profile_qt.h"
#include "resource_context_qt.h"
#include "type_conversion.h"
+#if defined(USE_NSS_CERTS)
+#include "net/cert_net/nss_ocsp.h"
+#endif
+
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+#include "net/cert/cert_net_fetcher.h"
+#include "net/cert_net/cert_net_fetcher_impl.h"
+#endif
+
namespace QtWebEngineCore {
static const char* const kDefaultAuthSchemes[] = { net::kBasicAuthScheme,
@@ -102,8 +111,6 @@ static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &f
return false;
if (first.enable_channel_id != second.enable_channel_id)
return false;
- if (first.enable_token_binding != second.enable_token_binding)
- return false;
return true;
}
@@ -153,7 +160,6 @@ static net::HttpNetworkSession::Params generateNetworkSessionParams(bool ignoreC
{
net::HttpNetworkSession::Params network_session_params;
network_session_params.ignore_certificate_errors = ignoreCertificateErrors;
- network_session_params.enable_token_binding = base::FeatureList::IsEnabled(features::kTokenBinding);
network_session_params.enable_channel_id = base::FeatureList::IsEnabled(features::kChannelID);
return network_session_params;
}
@@ -171,6 +177,16 @@ ProfileIODataQt::~ProfileIODataQt()
{
if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::IO))
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ if (m_useForGlobalCertificateVerification) {
+#if defined(USE_NSS_CERTS)
+ net::SetURLRequestContextForNSSHttpIO(nullptr);
+#endif
+#if defined(OS_LINUX) ||defined(OS_MACOSX)
+ net::ShutdownGlobalCertNetFetcher();
+#endif
+ }
+
m_resourceContext.reset();
if (m_cookieDelegate)
m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted
@@ -213,6 +229,7 @@ void ProfileIODataQt::initializeOnIOThread()
m_initialized = true;
generateAllStorage();
generateJobFactory();
+ setGlobalCertificateVerification();
}
void ProfileIODataQt::initializeOnUIThread()
@@ -276,7 +293,15 @@ void ProfileIODataQt::generateStorage()
net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0);
Q_ASSERT(proxyConfigService);
- m_storage->set_cert_verifier(net::CertVerifier::CreateDefault());
+ std::unique_ptr<net::CertVerifier> cert_verifier = net::CertVerifier::CreateDefault();
+ net::CertVerifier::Config config;
+ // Enable revocation checking:
+ config.enable_rev_checking = true;
+ // Mirroring Android WebView (we have no beef with Symantec, and our users might use them):
+ config.disable_symantec_enforcement = true;
+ cert_verifier->SetConfig(config);
+
+ m_storage->set_cert_verifier(std::move(cert_verifier));
std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier());
// FIXME:
// ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs());
@@ -307,7 +332,7 @@ void ProfileIODataQt::generateStorage()
scoped_refptr<base::SequencedTaskRunner> background_task_runner(
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(),
- base::TaskPriority::BACKGROUND,
+ base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
m_transportSecurityPersister =
std::make_unique<net::TransportSecurityPersister>(
@@ -347,7 +372,7 @@ void ProfileIODataQt::generateCookieStore()
channel_id_db = new net::SQLiteChannelIDStore(
toFilePath(m_channelIdPath),
base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND}));
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT}));
}
m_storage->set_channel_id_service(
@@ -367,8 +392,8 @@ void ProfileIODataQt::generateCookieStore()
base::FilePath(),
false,
false,
- nullptr)
- );
+ nullptr),
+ nullptr);
break;
case ProfileAdapter::AllowPersistentCookies:
cookieStore = content::CreateCookieStore(
@@ -376,8 +401,8 @@ void ProfileIODataQt::generateCookieStore()
toFilePath(m_cookiesPath),
false,
true,
- nullptr)
- );
+ nullptr),
+ nullptr);
break;
case ProfileAdapter::ForcePersistentCookies:
cookieStore = content::CreateCookieStore(
@@ -385,8 +410,8 @@ void ProfileIODataQt::generateCookieStore()
toFilePath(m_cookiesPath),
true,
true,
- nullptr)
- );
+ nullptr),
+ nullptr);
break;
}
@@ -494,13 +519,10 @@ void ProfileIODataQt::generateJobFactory()
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(
new net::DataProtocolHandler()));
scoped_refptr<base::TaskRunner> taskRunner(base::CreateTaskRunnerWithTraits({base::MayBlock(),
- base::TaskPriority::BACKGROUND,
+ base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
jobFactory->SetProtocolHandler(url::kFileScheme,
std::make_unique<net::FileProtocolHandler>(taskRunner));
- jobFactory->SetProtocolHandler(kQrcSchemeQt,
- std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(
- new QrcProtocolHandlerQt()));
jobFactory->SetProtocolHandler(url::kFtpScheme,
net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver()));
@@ -558,6 +580,21 @@ void ProfileIODataQt::regenerateJobFactory()
}
}
+void ProfileIODataQt::setGlobalCertificateVerification()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ QMutexLocker lock(&m_mutex);
+ if (m_useForGlobalCertificateVerification) {
+#if defined(USE_NSS_CERTS)
+ // Set request context used by NSS for OCSP requests.
+ net::SetURLRequestContextForNSSHttpIO(m_urlRequestContext.get());
+#endif
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+ net::SetGlobalCertNetFetcher(net::CreateCertNetFetcher(m_urlRequestContext.get()));
+#endif
+ }
+}
+
void ProfileIODataQt::setRequestContextData(content::ProtocolHandlerMap *protocolHandlers,
content::URLRequestInterceptorScopedVector request_interceptors)
{
@@ -580,6 +617,7 @@ void ProfileIODataQt::setFullConfiguration()
m_httpCachePath = m_profileAdapter->httpCachePath();
m_httpCacheMaxSize = m_profileAdapter->httpCacheMaxSize();
m_customUrlSchemes = m_profileAdapter->customUrlSchemes();
+ m_useForGlobalCertificateVerification = m_profileAdapter->isUsedForGlobalCertificateVerification();
m_dataPath = m_profileAdapter->dataPath();
}
@@ -605,12 +643,12 @@ void ProfileIODataQt::updateStorageSettings()
m_proxyConfigService =
new ProxyConfigServiceQt(
net::ProxyResolutionService::CreateSystemProxyConfigService(
- content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO)));
+ base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})));
//pass interface to io thread
m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithStrongBinding().PassInterface();
if (m_initialized)
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&ProfileIODataQt::generateAllStorage, m_weakPtr));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&ProfileIODataQt::generateAllStorage, m_weakPtr));
}
}
@@ -625,8 +663,8 @@ void ProfileIODataQt::updateCookieStore()
if (m_initialized && !m_updateAllStorage && !m_updateCookieStore) {
m_updateCookieStore = true;
m_updateHttpCache = true;
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&ProfileIODataQt::generateCookieStore, m_weakPtr));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&ProfileIODataQt::generateCookieStore, m_weakPtr));
}
}
@@ -639,8 +677,8 @@ void ProfileIODataQt::updateUserAgent()
if (m_initialized && !m_updateAllStorage && !m_updateUserAgent) {
m_updateUserAgent = true;
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&ProfileIODataQt::generateUserAgent, m_weakPtr));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&ProfileIODataQt::generateUserAgent, m_weakPtr));
}
}
@@ -663,8 +701,8 @@ void ProfileIODataQt::updateHttpCache()
if (m_initialized && !m_updateAllStorage && !m_updateHttpCache) {
m_updateHttpCache = true;
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&ProfileIODataQt::generateHttpCache, m_weakPtr));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&ProfileIODataQt::generateHttpCache, m_weakPtr));
}
}
@@ -677,8 +715,8 @@ void ProfileIODataQt::updateJobFactory()
if (m_initialized && !m_updateJobFactory) {
m_updateJobFactory = true;
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&ProfileIODataQt::regenerateJobFactory, m_weakPtr));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&ProfileIODataQt::regenerateJobFactory, m_weakPtr));
}
}
@@ -687,6 +725,7 @@ void ProfileIODataQt::updateRequestInterceptor()
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
QMutexLocker lock(&m_mutex);
m_requestInterceptor = m_profileAdapter->requestInterceptor();
+ m_hasPageInterceptors = m_profileAdapter->hasPageRequestInterceptor();
// We in this case do not need to regenerate any Chromium classes.
}
@@ -696,6 +735,13 @@ QWebEngineUrlRequestInterceptor *ProfileIODataQt::acquireInterceptor()
return m_requestInterceptor;
}
+bool ProfileIODataQt::hasPageInterceptors()
+{
+ // used in NetworkDelegateQt::OnBeforeURLRequest
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ return m_hasPageInterceptors;
+}
+
void ProfileIODataQt::releaseInterceptor()
{
m_mutex.unlock();
@@ -711,4 +757,15 @@ bool ProfileIODataQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url)
return m_cookieDelegate->canGetCookies(firstPartyUrl, url);
}
+void ProfileIODataQt::updateUsedForGlobalCertificateVerification()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ m_useForGlobalCertificateVerification = m_profileAdapter->isUsedForGlobalCertificateVerification();
+
+ if (m_useForGlobalCertificateVerification)
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&ProfileIODataQt::setGlobalCertificateVerification, m_weakPtr));
+}
+
} // namespace QtWebEngineCore
diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h
index 5b416861c..bcf49e22b 100644
--- a/src/core/profile_io_data_qt.h
+++ b/src/core/profile_io_data_qt.h
@@ -91,6 +91,7 @@ public:
void regenerateJobFactory();
bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const;
bool canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const;
+ void setGlobalCertificateVerification();
// Used in NetworkDelegateQt::OnBeforeURLRequest.
QWebEngineUrlRequestInterceptor *acquireInterceptor();
@@ -105,6 +106,8 @@ public:
void updateHttpCache(); // runs on ui thread
void updateJobFactory(); // runs on ui thread
void updateRequestInterceptor(); // runs on ui thread
+ void updateUsedForGlobalCertificateVerification(); // runs on ui thread
+ bool hasPageInterceptors();
private:
ProfileQt *m_profile;
@@ -145,6 +148,8 @@ private:
bool m_updateJobFactory = false;
bool m_updateUserAgent = false;
bool m_ignoreCertificateErrors = false;
+ bool m_useForGlobalCertificateVerification = false;
+ bool m_hasPageInterceptors = false;
base::WeakPtrFactory<ProfileIODataQt> m_weakPtrFactory; // this should be always the last member
QString m_dataPath;
DISALLOW_COPY_AND_ASSIGN(ProfileIODataQt);
diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp
index df05d891e..e4698c677 100644
--- a/src/core/profile_qt.cpp
+++ b/src/core/profile_qt.cpp
@@ -87,6 +87,8 @@ ProfileQt::ProfileQt(ProfileAdapter *profileAdapter)
registry->RegisterBooleanPref(spellcheck::prefs::kSpellCheckEnable, false);
registry->RegisterBooleanPref(spellcheck::prefs::kSpellCheckUseSpellingService, false);
#endif // QT_CONFIG(webengine_spellchecker)
+ registry->RegisterBooleanPref(prefs::kShowInternalAccessibilityTree, false);
+
m_prefService = factory.Create(registry);
user_prefs::UserPrefs::Set(this, m_prefService.get());
@@ -123,6 +125,11 @@ base::FilePath ProfileQt::GetPath() const
return toFilePath(m_profileAdapter->dataPath());
}
+base::FilePath ProfileQt::GetCachePath() const
+{
+ return toFilePath(m_profileAdapter->cachePath());
+}
+
bool ProfileQt::IsOffTheRecord() const
{
return m_profileAdapter->isOffTheRecord();
@@ -229,8 +236,8 @@ net::URLRequestContextGetter *ProfileQt::CreateRequestContextForStoragePartition
void ProfileQt::FailedToLoadDictionary(const std::string &language)
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- qWarning() << "Could not load dictionary for:" << toQt(language) << endl
- << "Make sure that correct bdic file is in:" << toQt(WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES).value());
+ LOG(WARNING) << "Could not load dictionary for:" << language;
+ LOG(INFO) << "Make sure that correct bdic file is in:" << WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES);
}
void ProfileQt::setSpellCheckLanguages(const QStringList &languages)
diff --git a/src/core/profile_qt.h b/src/core/profile_qt.h
index 00119c053..8641646b1 100644
--- a/src/core/profile_qt.h
+++ b/src/core/profile_qt.h
@@ -68,6 +68,7 @@ public:
// BrowserContext implementation:
base::FilePath GetPath() const override;
+ base::FilePath GetCachePath() const override;
bool IsOffTheRecord() const override;
net::URLRequestContextGetter *CreateMediaRequestContext() override;
diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni
index 14da1e6cf..3ae2b999c 100644
--- a/src/core/qtwebengine.gni
+++ b/src/core/qtwebengine.gni
@@ -9,6 +9,7 @@ chromium_version = exec_script("//build/util/version.py", [ "-f", rebase_path("/
include_dirs = [
"//skia/config",
"//third_party",
+ "//third_party/boringssl/src/include",
"//third_party/skia/include/core"
]
@@ -26,16 +27,14 @@ deps = [
"//components/web_cache/renderer",
"//components/spellcheck:buildflags",
"//content/public/app:browser",
- "//content/public/browser",
- "//content/public/common",
- "//content/public/renderer",
+ "//content",
"//media:media_buildflags",
"//net:net_with_v8",
"//services/proxy_resolver:lib",
"//skia",
"//third_party/blink/public:blink",
- "//third_party/mesa:mesa_headers",
"//ui/accessibility",
+ "//ui/gl",
"//qtwebengine/browser:interfaces",
":qtwebengine_sources",
":qtwebengine_resources"
@@ -49,6 +48,10 @@ if (is_linux && !is_desktop_linux) {
deps += [ "//ui/events/ozone:events_ozone_evdev"]
}
+if (use_xscrnsaver) {
+ deps += [ "//ui/base/x" ]
+}
+
if (use_ozone) {
deps += [
"//ui/ozone/common"
diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni
index b1361e727..aa9d12480 100644
--- a/src/core/qtwebengine_sources.gni
+++ b/src/core/qtwebengine_sources.gni
@@ -47,15 +47,13 @@ source_set("qtwebengine_sources") {
"//third_party/blink/public/mojom:mojom_platform",
]
sources = [
- "//chrome/common/custom_handlers/protocol_handler.cc",
- "//chrome/common/custom_handlers/protocol_handler.h",
+ "//chrome/browser/accessibility/accessibility_ui.cc",
+ "//chrome/browser/accessibility/accessibility_ui.h",
"//chrome/browser/custom_handlers/protocol_handler_registry.cc",
"//chrome/browser/custom_handlers/protocol_handler_registry.h",
"//chrome/browser/custom_handlers/protocol_handler_registry_factory.cc",
"//chrome/browser/custom_handlers/protocol_handler_registry_factory.h",
"//chrome/browser/media/webrtc/desktop_media_list.h",
- "//chrome/browser/media/webrtc/desktop_streams_registry.cc",
- "//chrome/browser/media/webrtc/desktop_streams_registry.h",
"//chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc",
"//chrome/browser/net/chrome_mojo_proxy_resolver_factory.h",
"//chrome/browser/profiles/profile.cc",
@@ -72,6 +70,8 @@ source_set("qtwebengine_sources") {
"//chrome/browser/ui/webui/quota_internals/quota_internals_ui.h",
"//chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.cc",
"//chrome/browser/ui/webui/task_scheduler_internals/task_scheduler_internals_ui.h",
+ "//chrome/common/custom_handlers/protocol_handler.cc",
+ "//chrome/common/custom_handlers/protocol_handler.h",
"//chrome/common/chrome_switches.cc",
"//chrome/common/chrome_switches.h",
"//chrome/common/pref_names.cc",
@@ -109,11 +109,6 @@ source_set("qtwebengine_sources") {
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
]
-
- deps += [
- # Need to depend on //content/ppapi_plugin, which is private, thus depending on parent.
- "//content",
- ]
}
if (enable_basic_printing || enable_print_preview) {
diff --git a/src/core/quota_permission_context_qt.cpp b/src/core/quota_permission_context_qt.cpp
index cb1467364..a502e7fc8 100644
--- a/src/core/quota_permission_context_qt.cpp
+++ b/src/core/quota_permission_context_qt.cpp
@@ -39,7 +39,9 @@
#include "quota_permission_context_qt.h"
+#include "base/task/post_task.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "quota_request_controller_impl.h"
@@ -64,10 +66,10 @@ void QuotaPermissionContextQt::RequestQuotaPermission(const StorageQuotaParams &
}
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::Bind(&QuotaPermissionContextQt::RequestQuotaPermission, this,
- params, render_process_id, callback));
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&QuotaPermissionContextQt::RequestQuotaPermission, this,
+ params, render_process_id, callback));
return;
}
@@ -95,10 +97,10 @@ void QuotaPermissionContextQt::dispatchCallbackOnIOThread(const PermissionCallba
return;
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
- content::BrowserThread::PostTask(
- content::BrowserThread::IO, FROM_HERE,
- base::Bind(&QuotaPermissionContextQt::dispatchCallbackOnIOThread,
- this, callback, response));
+ base::PostTaskWithTraits(
+ FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&QuotaPermissionContextQt::dispatchCallbackOnIOThread,
+ this, callback, response));
return;
}
diff --git a/src/core/qwebengineclientcertificatestore.cpp b/src/core/qwebengineclientcertificatestore.cpp
new file mode 100644
index 000000000..08f4389d7
--- /dev/null
+++ b/src/core/qwebengineclientcertificatestore.cpp
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "api/qwebengineclientcertificatestore.h"
+#include "client_cert_override_key_p.h"
+#include "client_cert_override_p.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
+#include "base/callback_forward.h"
+
+#include "net/ssl/client_cert_store.h"
+#include "net/ssl/ssl_cert_request_info.h"
+#include "net/cert/x509_certificate.h"
+
+#include "third_party/boringssl/src/include/openssl/pem.h"
+#include "third_party/boringssl/src/include/openssl/err.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+
+#if defined(USE_NSS_CERTS)
+#include "net/ssl/client_cert_store_nss.h"
+#endif
+
+#if defined(OS_WIN)
+#include "net/ssl/client_cert_store_win.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "net/ssl/client_cert_store_mac.h"
+#endif
+
+#include <QByteArray>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(ssl)
+
+typedef struct OverrideData {
+ QSslKey key;
+ QSslCertificate certificate;
+ scoped_refptr<net::X509Certificate> certPtr;
+ scoped_refptr<net::SSLPrivateKey> keyPtr;
+} OverrideData;
+
+struct QWebEngineClientCertificateStoreData {
+ QList<OverrideData*> deletedCerts;
+};
+
+static QList<OverrideData*> ClientCertOverrideData;
+QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::m_instance = NULL;
+
+/*!
+ \class QWebEngineClientCertificateStore::Entry
+ \inmodule QtWebEngineCore
+ \since 5.13
+ \brief This structure holds the certificate and the private key.
+*/
+
+/*!
+ \class QWebEngineClientCertificateStore
+ \inmodule QtWebEngineCore
+ \since 5.13
+ \brief The QWebEngineClientCertificateStore class provides an in-memory store for client certificates.
+
+ The class allows to store client certificates in an in-memory store.
+ When a web site requests an SSL client certificate, the QWebEnginePage::selectClientCertificate
+ signal is emitted with matching certificates from the native certificate store or the in-memory store.
+ The getInstance() method can be used to access the single instance of the class.
+*/
+
+QWebEngineClientCertificateStore::QWebEngineClientCertificateStore()
+{
+ this->d_ptr = new QWebEngineClientCertificateStoreData;
+}
+
+/*!
+ Destroys this QWebEngineClientCertificateStore object.
+*/
+
+QWebEngineClientCertificateStore::~QWebEngineClientCertificateStore()
+{
+ // Just in case user has not deleted in-memory certificates
+ clear();
+
+ qDeleteAll(d_ptr->deletedCerts);
+ delete d_ptr;
+}
+
+/*!
+ Returns an in-memory client certificate store.
+*/
+
+QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::getInstance()
+{
+ if (!m_instance)
+ m_instance = new QWebEngineClientCertificateStore;
+ return m_instance;
+}
+
+/*!
+ Adds a \a certificate with the \a privateKey to the in-memory client certificate store.
+*/
+
+void QWebEngineClientCertificateStore::add(const QSslCertificate &certificate, const QSslKey &privateKey)
+{
+
+ QByteArray sslKeyInBytes = privateKey.toPem();
+ QByteArray certInBytes = certificate.toDer();
+
+ OverrideData* data = new OverrideData;
+ data->keyPtr = net::WrapOpenSSLPrivateKey(sslKeyInBytes);
+ data->certPtr = net::X509Certificate::CreateFromBytes(
+ certInBytes.data(), certInBytes.length());
+ data->key = privateKey;
+ data->certificate = certificate;
+ ClientCertOverrideData.append(data);
+}
+
+/*!
+ Returns a list of private and public keys of client certificates in the in-memory store.
+ Returns an empty list if the in-memory store does not contain certificates.
+*/
+
+QList<QWebEngineClientCertificateStore::Entry> QWebEngineClientCertificateStore::toList() const
+{
+ QList<Entry> certificateList;
+ for (auto data : ClientCertOverrideData) {
+ Entry entry;
+ entry.certificate = data->certificate;
+ entry.privateKey = data->key;
+ certificateList.append(entry);
+ }
+ return certificateList;
+}
+
+/*!
+ Deletes all the instances of the client certificate in the in-memory client certificate store
+ that matches the certificate in the \a entry.
+*/
+
+void QWebEngineClientCertificateStore::remove(Entry entry)
+{
+ QMutableListIterator<OverrideData*> iterator(ClientCertOverrideData);
+ while (iterator.hasNext()) {
+ auto overrideData = iterator.next();
+ if (entry.certificate.toDer() == overrideData->certificate.toDer()) {
+ d_ptr->deletedCerts.append(overrideData);
+ iterator.remove();
+ }
+ }
+}
+
+/*!
+ Clears all the client certificates from the in-memory store.
+*/
+
+void QWebEngineClientCertificateStore::clear()
+{
+ for (auto data : ClientCertOverrideData)
+ d_ptr->deletedCerts.append(data);
+ ClientCertOverrideData.clear();
+}
+
+#endif // QT_CONFIG(ssl)
+
+QT_END_NAMESPACE
+
+namespace net {
+
+namespace {
+
+class ClientCertIdentityOverride : public ClientCertIdentity {
+public:
+ ClientCertIdentityOverride(
+ scoped_refptr<net::X509Certificate> cert,
+ scoped_refptr<net::SSLPrivateKey> key)
+ : ClientCertIdentity(std::move(cert)),
+ key_(std::move(key)) {}
+ ~ClientCertIdentityOverride() override = default;
+
+ void AcquirePrivateKey(
+ const base::Callback<void(scoped_refptr<SSLPrivateKey>)>&
+ private_key_callback) override
+ {
+ private_key_callback.Run(key_);
+ }
+
+#if defined(OS_MACOSX)
+ SecIdentityRef sec_identity_ref() const override
+ {
+ return nullptr;
+ }
+#endif
+
+private:
+ scoped_refptr<net::SSLPrivateKey> key_;
+};
+
+} // namespace
+
+
+ClientCertOverrideStore::ClientCertOverrideStore()
+ : ClientCertStore()
+{
+}
+
+ClientCertOverrideStore::~ClientCertOverrideStore()
+{
+}
+
+void ClientCertOverrideStore::GetClientCerts(const SSLCertRequestInfo &cert_request_info,
+ const ClientCertListCallback &callback)
+{
+#if QT_CONFIG(ssl)
+ // Look for certificates in memory store
+ for (int i = 0; i < ClientCertOverrideData.length(); i++) {
+ scoped_refptr<net::X509Certificate> cert = ClientCertOverrideData[i]->certPtr;
+ if (cert != NULL && cert->IsIssuedByEncoded(cert_request_info.cert_authorities)) {
+ ClientCertIdentityList selected_identities;
+ selected_identities.push_back(std::make_unique<ClientCertIdentityOverride>(cert, ClientCertOverrideData[i]->keyPtr));
+ callback.Run(std::move(selected_identities));
+ return;
+ }
+ }
+#endif // QT_CONFIG(ssl)
+
+ // Continue with native cert store if matching certificate is not found in memory
+ std::unique_ptr<net::ClientCertStore> store = getNativeStore();
+ if (store != NULL) {
+ store->GetClientCerts(cert_request_info, callback);
+ return;
+ }
+
+ callback.Run(ClientCertIdentityList());
+ return;
+}
+
+std::unique_ptr<net::ClientCertStore> ClientCertOverrideStore::getNativeStore()
+{
+#if defined(USE_NSS_CERTS)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory()));
+#elif defined(OS_WIN)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
+#elif defined(OS_MACOSX)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
+#else
+ return nullptr;
+#endif
+}
+}
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 40ed75973..ac7357f0e 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -41,17 +41,20 @@
#include "browser_accessibility_manager_qt.h"
#include "chromium_overrides.h"
-#include "compositor.h"
+#include "compositor/compositor.h"
#include "qtwebenginecoreglobal_p.h"
#include "render_widget_host_view_qt_delegate.h"
+#include "touch_handle_drawable_client.h"
+#include "touch_selection_controller_client_qt.h"
+#include "touch_selection_menu_controller.h"
#include "type_conversion.h"
#include "web_contents_adapter_client.h"
#include "web_event_factory.h"
#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
-#include "content/browser/accessibility/browser_accessibility_state_impl.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/content_switches_internal.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
@@ -61,9 +64,12 @@
#include "third_party/blink/public/platform/web_cursor_info.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/event.h"
+#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/gesture_detection/motion_event.h"
#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/touch_selection/touch_selection_controller.h"
#if defined(USE_OZONE)
#include "ui/base/clipboard/scoped_clipboard_writer.h"
@@ -82,7 +88,6 @@
#include <QFocusEvent>
#include <QGuiApplication>
#include <QInputMethodEvent>
-#include <QLoggingCategory>
#include <QTextFormat>
#include <QKeyEvent>
#include <QMouseEvent>
@@ -93,7 +98,6 @@
#include <QWheelEvent>
#include <QWindow>
#include <QtGui/private/qinputcontrol_p.h>
-#include <QtGui/qaccessible.h>
namespace QtWebEngineCore {
@@ -224,6 +228,8 @@ public:
float GetPressure(size_t pointer_index) const override { return touchPoints.at(pointer_index).pressure(); }
float GetTiltX(size_t pointer_index) const override { return 0; }
float GetTiltY(size_t pointer_index) const override { return 0; }
+ float GetTwist(size_t) const override { return 0; }
+ float GetTangentialPressure(size_t) const override { return 0; }
base::TimeTicks GetEventTime() const override { return eventTime; }
size_t GetHistorySize() const override { return 0; }
@@ -244,25 +250,12 @@ private:
float dpiScale;
};
-bool isAccessibilityEnabled() {
- // On Linux accessibility is disabled by default due to performance issues,
- // and can be re-enabled by setting the QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment
- // variable. For details, see QTBUG-59922.
-#ifdef Q_OS_LINUX
- static bool accessibility_enabled
- = qEnvironmentVariableIsSet("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY");
-#else
- const bool accessibility_enabled = true;
-#endif
- return accessibility_enabled;
-}
-
RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget)
: content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget)
, m_gestureProvider(QtGestureProviderConfig(), this)
, m_sendMotionActionDown(false)
, m_touchMotionStarted(false)
- , m_compositor(new Compositor(this))
+ , m_compositor(new Compositor(widget))
, m_loadVisuallyCommittedState(NotCommitted)
, m_adapterClient(0)
, m_imeInProgress(false)
@@ -280,13 +273,6 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget
base::checked_cast<uint32_t>(widget->GetRoutingID()))
{
host()->SetView(this);
-#ifndef QT_NO_ACCESSIBILITY
- if (isAccessibilityEnabled()) {
- QAccessible::installActivationObserver(this);
- if (QAccessible::isActive())
- content::BrowserAccessibilityStateImpl::GetInstance()->EnableAccessibility();
- }
-#endif // QT_NO_ACCESSIBILITY
if (GetTextInputManager())
GetTextInputManager()->AddObserver(this);
@@ -294,27 +280,31 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget
const QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
m_imeHasHiddenTextCapability = context && context->hasCapability(QPlatformInputContext::HiddenTextCapability);
- m_localSurfaceId = m_localSurfaceIdAllocator.GenerateId();
-
if (host()->delegate() && host()->delegate()->GetInputEventRouter())
host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(GetFrameSinkId(), this);
+
+ m_touchSelectionControllerClient.reset(new TouchSelectionControllerClientQt(this));
+ ui::TouchSelectionController::Config config;
+ config.max_tap_duration = base::TimeDelta::FromMilliseconds(ui::GestureConfiguration::GetInstance()->long_press_time_in_ms());
+ config.tap_slop = ui::GestureConfiguration::GetInstance()->max_touch_move_in_pixels_for_click();
+ config.enable_longpress_drag_selection = false;
+ m_touchSelectionController.reset(new ui::TouchSelectionController(m_touchSelectionControllerClient.get(), config));
}
RenderWidgetHostViewQt::~RenderWidgetHostViewQt()
{
QObject::disconnect(m_adapterClientDestroyedConnection);
-#ifndef QT_NO_ACCESSIBILITY
- QAccessible::removeActivationObserver(this);
-#endif // QT_NO_ACCESSIBILITY
if (text_input_manager_)
text_input_manager_->RemoveObserver(this);
+
+ m_touchSelectionController.reset();
+ m_touchSelectionControllerClient.reset();
}
void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate)
{
m_delegate.reset(delegate);
- m_compositor->setViewDelegate(delegate);
}
void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterClient)
@@ -682,9 +672,9 @@ void RenderWidgetHostViewQt::DidCreateNewRendererCompositorFrameSink(viz::mojom:
void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, viz::CompositorFrame frame, base::Optional<viz::HitTestRegionList>)
{
bool scrollOffsetChanged = (m_lastScrollOffset != frame.metadata.root_scroll_offset);
- bool contentsSizeChanged = (m_lastContentsSize != frame.metadata.root_layer_size);
+ bool contentsSizeChanged = (m_lastContentsSize != frame.metadata.scrollable_viewport_size);
m_lastScrollOffset = frame.metadata.root_scroll_offset;
- m_lastContentsSize = frame.metadata.root_layer_size;
+ m_lastContentsSize = frame.metadata.scrollable_viewport_size;
// Force to process swap messages
uint32_t frame_token = frame.metadata.frame_token;
@@ -696,7 +686,9 @@ void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &lo
if (dpiScale != 0 && dpiScale != 1)
frame.metadata.device_scale_factor /= dpiScale;
- m_compositor->submitFrame(std::move(frame));
+ m_compositor->submitFrame(
+ std::move(frame),
+ base::BindOnce(&RenderWidgetHostViewQtDelegate::update, base::Unretained(m_delegate.get())));
if (m_loadVisuallyCommittedState == NotCommitted) {
m_loadVisuallyCommittedState = DidFirstCompositorFrameSwap;
@@ -902,7 +894,33 @@ void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture)
return;
}
- host()->ForwardGestureEvent(ui::CreateWebGestureEventFromGestureEventData(gesture));
+ blink::WebGestureEvent event = ui::CreateWebGestureEventFromGestureEventData(gesture);
+
+ if (m_touchSelectionController && m_touchSelectionControllerClient) {
+ switch (event.GetType()) {
+ case blink::WebInputEvent::kGestureLongPress:
+ m_touchSelectionController->HandleLongPressEvent(event.TimeStamp(), event.PositionInWidget());
+ break;
+ case blink::WebInputEvent::kGestureTap:
+ m_touchSelectionController->HandleTapEvent(event.PositionInWidget(), event.data.tap.tap_count);
+ break;
+ case blink::WebInputEvent::kGestureScrollBegin:
+ m_touchSelectionControllerClient->onScrollBegin();
+ break;
+ case blink::WebInputEvent::kGestureScrollEnd:
+ m_touchSelectionControllerClient->onScrollEnd();
+ break;
+ default:
+ break;
+ }
+ }
+
+ host()->ForwardGestureEvent(event);
+}
+
+void RenderWidgetHostViewQt::DidStopFlinging()
+{
+ m_touchSelectionControllerClient->DidStopFlinging();
}
viz::ScopedSurfaceIdAllocator RenderWidgetHostViewQt::DidUpdateVisualProperties(const cc::RenderFrameMetadata &metadata)
@@ -918,7 +936,7 @@ void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::Rende
if (metadata.local_surface_id)
m_localSurfaceIdAllocator.UpdateFromChild(*metadata.local_surface_id);
- m_localSurfaceId = m_localSurfaceIdAllocator.GenerateId();
+ m_localSurfaceIdAllocator.GenerateId();
host()->SendScreenRects();
if (m_pendingResize) {
if (host()->SynchronizeVisualProperties())
@@ -928,7 +946,7 @@ void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::Rende
QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode)
{
- return m_compositor->updatePaintNode(oldNode);
+ return m_compositor->updatePaintNode(oldNode, m_delegate.get());
}
void RenderWidgetHostViewQt::notifyResize()
@@ -1171,7 +1189,7 @@ float RenderWidgetHostViewQt::dpiScale() const
bool RenderWidgetHostViewQt::IsPopup() const
{
- return popup_type_ != blink::kWebPopupTypeNone;
+ return widget_type_ == content::WidgetType::kPopup;
}
void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event)
@@ -1313,9 +1331,9 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
}
if (hasSelection) {
- content::RenderFrameHostImpl *frameHost = static_cast<content::RenderFrameHostImpl *>(getFocusedFrameHost());
- if (frameHost)
- frameHost->GetFrameInputHandler()->SetEditableSelectionOffsets(selectionRange.start(), selectionRange.end());
+ content::mojom::FrameInputHandler *frameInputHandler = getFrameInputHandler();
+ if (frameInputHandler)
+ frameInputHandler->SetEditableSelectionOffsets(selectionRange.start(), selectionRange.end());
}
int replacementLength = ev->replacementLength();
@@ -1392,16 +1410,6 @@ void RenderWidgetHostViewQt::handleInputMethodQueryEvent(QInputMethodQueryEvent
ev->accept();
}
-#ifndef QT_NO_ACCESSIBILITY
-void RenderWidgetHostViewQt::accessibilityActiveChanged(bool active)
-{
- if (active)
- content::BrowserAccessibilityStateImpl::GetInstance()->EnableAccessibility();
- else
- content::BrowserAccessibilityStateImpl::GetInstance()->DisableAccessibility();
-}
-#endif // QT_NO_ACCESSIBILITY
-
void RenderWidgetHostViewQt::handleWheelEvent(QWheelEvent *ev)
{
if (!m_wheelAckPending) {
@@ -1459,9 +1467,6 @@ void RenderWidgetHostViewQt::handleGestureEvent(QNativeGestureEvent *ev)
}
#endif
-Q_DECLARE_LOGGING_CATEGORY(QWEBENGINE_TOUCH_HANDLING);
-Q_LOGGING_CATEGORY(QWEBENGINE_TOUCH_HANDLING, "qt.webengine.touch");
-
void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
{
// On macOS instead of handling touch events, we use the OS provided QNativeGestureEvents.
@@ -1469,7 +1474,7 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
if (ev->spontaneous()) {
return;
} else {
- qCWarning(QWEBENGINE_TOUCH_HANDLING)
+ VLOG(1)
<< "Sending simulated touch events to Chromium does not work properly on macOS. "
"Consider using QNativeGestureEvents or QMouseEvents.";
}
@@ -1486,11 +1491,35 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
eventTimestamp += m_eventsToNowDelta;
QList<QTouchEvent::TouchPoint> touchPoints = mapTouchPointIds(ev->touchPoints());
+ {
+ ui::MotionEvent::Action action;
+ switch (touchPoints[0].state()) {
+ case Qt::TouchPointPressed:
+ action = ui::MotionEvent::Action::DOWN;
+ break;
+ case Qt::TouchPointMoved:
+ action = ui::MotionEvent::Action::MOVE;
+ break;
+ case Qt::TouchPointReleased:
+ action = ui::MotionEvent::Action::UP;
+ break;
+ default:
+ action = ui::MotionEvent::Action::NONE;
+ break;
+ }
+
+ MotionEventQt motionEvent(touchPoints, eventTimestamp, action, ev->modifiers(), dpiScale(), 0);
+ if (m_touchSelectionController->WillHandleTouchEvent(motionEvent)) {
+ ev->accept();
+ return;
+ }
+ }
switch (ev->type()) {
case QEvent::TouchBegin:
m_sendMotionActionDown = true;
m_touchMotionStarted = true;
+ m_touchSelectionControllerClient->onTouchDown();
break;
case QEvent::TouchUpdate:
m_touchMotionStarted = true;
@@ -1517,6 +1546,7 @@ void RenderWidgetHostViewQt::handleTouchEvent(QTouchEvent *ev)
}
case QEvent::TouchEnd:
clearPreviousTouchMotionState();
+ m_touchSelectionControllerClient->onTouchUp();
break;
default:
break;
@@ -1654,11 +1684,6 @@ void RenderWidgetHostViewQt::SetNeedsBeginFrames(bool needs_begin_frames)
m_compositor->setNeedsBeginFrames(needs_begin_frames);
}
-void RenderWidgetHostViewQt::OnBeginFrame(base::TimeTicks frame_time)
-{
- host()->ProgressFlingIfNeeded(frame_time);
-}
-
content::RenderFrameHost *RenderWidgetHostViewQt::getFocusedFrameHost()
{
content::RenderViewHostImpl *viewHost = content::RenderViewHostImpl::From(host());
@@ -1672,6 +1697,15 @@ content::RenderFrameHost *RenderWidgetHostViewQt::getFocusedFrameHost()
return focusedFrame->current_frame_host();
}
+content::mojom::FrameInputHandler *RenderWidgetHostViewQt::getFrameInputHandler()
+{
+ content::RenderFrameHostImpl *frameHost = static_cast<content::RenderFrameHostImpl *>(getFocusedFrameHost());
+ if (!frameHost)
+ return nullptr;
+
+ return frameHost->GetFrameInputHandler();
+}
+
ui::TextInputType RenderWidgetHostViewQt::getTextInputType() const
{
if (text_input_manager_ && text_input_manager_->GetTextInputState())
@@ -1696,7 +1730,7 @@ const viz::FrameSinkId &RenderWidgetHostViewQt::GetFrameSinkId() const
const viz::LocalSurfaceId &RenderWidgetHostViewQt::GetLocalSurfaceId() const
{
- return m_localSurfaceId;
+ return m_localSurfaceIdAllocator.GetCurrentLocalSurfaceId();
}
void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view)
@@ -1710,14 +1744,29 @@ void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostVi
void RenderWidgetHostViewQt::EnsureSurfaceSynchronizedForLayoutTest()
{
- ++m_latestCaptureSequenceNumber;
- if (host())
- host()->SynchronizeVisualProperties();
+ NOTIMPLEMENTED();
}
uint32_t RenderWidgetHostViewQt::GetCaptureSequenceNumber() const
{
- return m_latestCaptureSequenceNumber;
+ return 0;
+}
+
+void RenderWidgetHostViewQt::ResetFallbackToFirstNavigationSurface()
+{
+ Q_UNIMPLEMENTED();
+}
+
+void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation()
+{
+ content::RenderWidgetHostViewBase::OnRenderFrameMetadataChangedAfterActivation();
+
+ const cc::RenderFrameMetadata &metadata = host()->render_frame_metadata_provider()->LastRenderFrameMetadata();
+ if (metadata.selection.start != m_selectionStart || metadata.selection.end != m_selectionEnd) {
+ m_selectionStart = metadata.selection.start;
+ m_selectionEnd = metadata.selection.end;
+ m_touchSelectionControllerClient->UpdateClientSelectionBounds(m_selectionStart, m_selectionEnd);
+ }
}
} // namespace QtWebEngineCore
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index a12ffe636..b9efc996f 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -50,14 +50,12 @@
#include "content/browser/renderer_host/input/mouse_wheel_phase_handler.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/text_input_manager.h"
-#include "content/common/view_messages.h"
#include "gpu/ipc/common/gpu_messages.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
#include "qtwebenginecoreglobal_p.h"
#include <QMap>
#include <QPoint>
#include <QtGlobal>
-#include <QtGui/qaccessible.h>
#include <QtGui/QTouchEvent>
QT_BEGIN_NAMESPACE
@@ -67,11 +65,21 @@ QT_END_NAMESPACE
namespace content {
class RenderFrameHost;
class RenderWidgetHostImpl;
+namespace mojom {
+class FrameInputHandler;
+}
+}
+
+namespace ui {
+class TouchSelectionController;
}
namespace QtWebEngineCore {
class Compositor;
+class TouchHandleDrawableClient;
+class TouchSelectionControllerClientQt;
+class TouchSelectionMenuController;
struct MultipleMouseClickHelper
{
@@ -94,9 +102,6 @@ class RenderWidgetHostViewQt
, public ui::GestureProviderClient
, public RenderWidgetHostViewQtDelegateClient
, public base::SupportsWeakPtr<RenderWidgetHostViewQt>
-#ifndef QT_NO_ACCESSIBILITY
- , public QAccessible::ActivationObserver
-#endif // QT_NO_ACCESSIBILITY
, public content::TextInputManager::Observer
{
public:
@@ -111,8 +116,8 @@ public:
RenderWidgetHostViewQtDelegate *delegate() { return m_delegate.get(); }
void setDelegate(RenderWidgetHostViewQtDelegate *delegate);
+ WebContentsAdapterClient *adapterClient() { return m_adapterClient; }
void setAdapterClient(WebContentsAdapterClient *adapterClient);
- void OnBeginFrame(base::TimeTicks frame_time);
void InitAsChild(gfx::NativeView) override;
void InitAsPopup(content::RenderWidgetHostView*, const gfx::Rect&) override;
@@ -163,6 +168,8 @@ public:
void TakeFallbackContentFrom(content::RenderWidgetHostView *view) override;
void EnsureSurfaceSynchronizedForLayoutTest() override;
uint32_t GetCaptureSequenceNumber() const override;
+ void ResetFallbackToFirstNavigationSurface() override;
+ void DidStopFlinging() override;
// Overridden from ui::GestureProviderClient.
void OnGestureEvent(const ui::GestureEventData& gesture) override;
@@ -209,15 +216,20 @@ public:
// Overridden from content::BrowserAccessibilityDelegate
content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
-#ifndef QT_NO_ACCESSIBILITY
- void accessibilityActiveChanged(bool active) override;
-#endif // QT_NO_ACCESSIBILITY
LoadVisuallyCommittedState getLoadVisuallyCommittedState() const { return m_loadVisuallyCommittedState; }
void setLoadVisuallyCommittedState(LoadVisuallyCommittedState state) { m_loadVisuallyCommittedState = state; }
+ // Overridden from content::RenderFrameMetadataProvider::Observer
+ void OnRenderFrameMetadataChangedAfterActivation() override;
+
gfx::SizeF lastContentsSize() const { return m_lastContentsSize; }
gfx::Vector2dF lastScrollOffset() const { return m_lastScrollOffset; }
+ ui::TouchSelectionController *getTouchSelectionController() const { return m_touchSelectionController.get(); }
+ TouchSelectionControllerClientQt *getTouchSelectionControllerClient() const { return m_touchSelectionControllerClient.get(); }
+ content::mojom::FrameInputHandler *getFrameInputHandler();
+ ui::TextInputType getTextInputType() const;
+
private:
void processMotionEvent(const ui::MotionEvent &motionEvent);
void clearPreviousTouchMotionState();
@@ -229,7 +241,6 @@ private:
void selectionChanged();
content::RenderFrameHost *getFocusedFrameHost();
- ui::TextInputType getTextInputType() const;
ui::FilteredGestureProvider m_gestureProvider;
base::TimeDelta m_eventsToNowDelta;
@@ -252,7 +263,6 @@ private:
gfx::Vector2dF m_lastScrollOffset;
gfx::SizeF m_lastContentsSize;
- viz::LocalSurfaceId m_localSurfaceId;
viz::ParentLocalSurfaceIdAllocator m_localSurfaceIdAllocator;
uint m_imState;
@@ -270,8 +280,12 @@ private:
content::MouseWheelPhaseHandler m_mouseWheelPhaseHandler;
viz::FrameSinkId m_frameSinkId;
- uint32_t m_latestCaptureSequenceNumber = 0u;
std::string m_editCommand;
+
+ std::unique_ptr<TouchSelectionControllerClientQt> m_touchSelectionControllerClient;
+ std::unique_ptr<ui::TouchSelectionController> m_touchSelectionController;
+ gfx::SelectionBound m_selectionStart;
+ gfx::SelectionBound m_selectionEnd;
};
} // namespace QtWebEngineCore
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
index 403448b91..5aaf7ab7b 100644
--- a/src/core/renderer/content_renderer_client_qt.cpp
+++ b/src/core/renderer/content_renderer_client_qt.cpp
@@ -137,7 +137,8 @@ void ContentRendererClientQt::RenderThreadStarted()
// Allow XMLHttpRequests from qrc to file.
blink::WebURL qrc(blink::KURL("qrc:"));
blink::WebString file(blink::WebString::FromASCII("file"));
- blink::WebSecurityPolicy::AddOriginAccessWhitelistEntry(qrc, file, blink::WebString(), true);
+ blink::WebSecurityPolicy::AddOriginAccessAllowListEntry(qrc, file, blink::WebString(), true,
+ network::mojom::CORSOriginAccessMatchPriority::kDefaultPriority);
}
void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view)
@@ -230,6 +231,7 @@ void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderF
error_page::LocalizedError::GetStrings(
error.reason(), error.domain(), error.url(), isPost,
error.stale_copy_in_cache(), false, false,
+ error_page::LocalizedError::OfflineContentOnNetErrorFeatureState::kDisabled,
locale, std::unique_ptr<error_page::ErrorPageParams>(), &errorStrings);
resourceId = IDR_NET_ERROR_HTML;
diff --git a/src/core/renderer/content_settings_observer_qt.cpp b/src/core/renderer/content_settings_observer_qt.cpp
index 045098457..c1495e1fe 100644
--- a/src/core/renderer/content_settings_observer_qt.cpp
+++ b/src/core/renderer/content_settings_observer_qt.cpp
@@ -93,8 +93,8 @@ bool ContentSettingsObserverQt::OnMessageReceived(const IPC::Message& message)
return handled;
}
-void ContentSettingsObserverQt::DidCommitProvisionalLoad(bool /*is_new_navigation*/,
- bool is_same_document_navigation)
+void ContentSettingsObserverQt::DidCommitProvisionalLoad(bool is_same_document_navigation,
+ ui::PageTransition /*transition*/)
{
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
if (frame->Parent())
diff --git a/src/core/renderer/content_settings_observer_qt.h b/src/core/renderer/content_settings_observer_qt.h
index 981655f20..a9bee3d2d 100644
--- a/src/core/renderer/content_settings_observer_qt.h
+++ b/src/core/renderer/content_settings_observer_qt.h
@@ -80,8 +80,8 @@ private:
// RenderFrameObserver implementation:
bool OnMessageReceived(const IPC::Message &message) override;
- void DidCommitProvisionalLoad(bool is_new_navigation,
- bool is_same_document_navigation) override;
+ void DidCommitProvisionalLoad(bool is_same_document_navigation,
+ ui::PageTransition transition) override;
void OnDestruct() override;
// Message handlers.
diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp
index 920fda72e..46f5de2c2 100644
--- a/src/core/renderer/user_resource_controller.cpp
+++ b/src/core/renderer/user_resource_controller.cpp
@@ -103,7 +103,7 @@ static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url)
matchFound = false;
for (auto it = scriptData.urlPatterns.begin(), end = scriptData.urlPatterns.end(); it != end; ++it) {
URLPattern urlPattern(validUserScriptSchemes());
- if (urlPattern.Parse(*it) == URLPattern::PARSE_SUCCESS && urlPattern.MatchesURL(url))
+ if (urlPattern.Parse(*it) == URLPattern::ParseResult::kSuccess && urlPattern.MatchesURL(url))
matchFound = true;
}
if (!matchFound)
@@ -137,7 +137,7 @@ public:
private:
// RenderFrameObserver implementation.
- void DidCommitProvisionalLoad(bool is_new_navigation, bool is_same_document_navigation) override;
+ void DidCommitProvisionalLoad(bool is_same_document_navigation, ui::PageTransition transition) override;
void DidClearWindowObject() override;
void DidFinishDocumentLoad() override;
void DidFinishLoad() override;
@@ -230,8 +230,8 @@ UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(conte
{
}
-void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad(bool /* is_new_navigation */,
- bool is_same_document_navigation)
+void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad(bool is_same_document_navigation,
+ ui::PageTransition /*transitionbool*/)
{
if (is_same_document_navigation)
return;
diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp
index 1f496e810..f1da8289a 100644
--- a/src/core/renderer/web_channel_ipc_transport.cpp
+++ b/src/core/renderer/web_channel_ipc_transport.cpp
@@ -137,6 +137,8 @@ void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args)
args->ThrowTypeError("Missing argument");
return;
}
+ v8::Isolate *isolate = blink::MainThreadIsolate();
+ v8::HandleScope handleScope(isolate);
if (!jsonValue->IsString()) {
args->ThrowTypeError("Expected string");
@@ -144,10 +146,10 @@ void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args)
}
v8::Local<v8::String> jsonString = v8::Local<v8::String>::Cast(jsonValue);
- QByteArray json(jsonString->Utf8Length(), 0);
- jsonString->WriteUtf8(json.data(), json.size(),
- nullptr,
- v8::String::REPLACE_INVALID_UTF8);
+ QByteArray json(jsonString->Utf8Length(isolate), 0);
+ jsonString->WriteUtf8(isolate,
+ json.data(), json.size(),
+ nullptr, v8::String::REPLACE_INVALID_UTF8);
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(json, &error);
diff --git a/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp b/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp
index 2c8b1246a..5d7c3973f 100644
--- a/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp
+++ b/src/core/renderer_host/pepper/pepper_isolated_file_system_message_filter.cpp
@@ -45,8 +45,10 @@
#include "pepper_isolated_file_system_message_filter.h"
#include "base/macros.h"
+#include "base/task/post_task.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_view_host.h"
@@ -83,7 +85,7 @@ scoped_refptr<base::TaskRunner> PepperIsolatedFileSystemMessageFilter::OverrideT
{
// In order to reach ExtensionSystem, we need to get ProfileManager first.
// ProfileManager lives in UI thread, so we need to do this in UI thread.
- return content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI);
+ return base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI});
}
int32_t PepperIsolatedFileSystemMessageFilter::OnResourceMessageReceived(const IPC::Message& msg, ppapi::host::HostMessageContext *context)
diff --git a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp
index 428faa34e..dc7507f34 100644
--- a/src/core/resource_bundle_qt.cpp
+++ b/src/core/resource_bundle_qt.cpp
@@ -71,6 +71,7 @@ gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id)
return GetEmptyImage();
}
+// static
bool ResourceBundle::LocaleDataPakExists(const std::string& locale)
{
#if defined(OS_LINUX)
diff --git a/src/core/service/service_qt.cpp b/src/core/service/service_qt.cpp
index 30ed269e8..bb842232c 100644
--- a/src/core/service/service_qt.cpp
+++ b/src/core/service/service_qt.cpp
@@ -45,7 +45,9 @@
#include "service_qt.h"
#include "base/no_destructor.h"
+#include "base/task/post_task.h"
#include "components/spellcheck/spellcheck_buildflags.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "services/service_manager/public/cpp/binder_registry.h"
@@ -82,10 +84,10 @@ private:
ServiceQt::IOThreadContext::IOThreadContext()
{
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
- content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI);
#if BUILDFLAG(ENABLE_SPELLCHECK)
- m_registry_with_source_info.AddInterface(base::Bind(&SpellCheckHostChromeImpl::Create), ui_task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI});
+ m_registry_with_source_info.AddInterface(base::BindRepeating(&SpellCheckHostChromeImpl::Create), ui_task_runner);
#endif
}
@@ -97,7 +99,7 @@ void ServiceQt::IOThreadContext::BindConnector(service_manager::mojom::Connector
// on the IO thread. Post a task instead. As long as this task is posted
// before any code attempts to connect to the chrome service, there's no
// race.
- content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO)->PostTask(
+ base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})->PostTask(
FROM_HERE,
base::BindOnce(&IOThreadContext::BindConnectorOnIOThread,
base::Unretained(this),
diff --git a/src/core/net/qrc_protocol_handler_qt.h b/src/core/touch_handle_drawable_client.h
index f2849c1ef..42d907d75 100644
--- a/src/core/net/qrc_protocol_handler_qt.h
+++ b/src/core/touch_handle_drawable_client.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -37,34 +37,24 @@
**
****************************************************************************/
-#ifndef QRC_PROTOCOL_HANDLER_QT_H_
-#define QRC_PROTOCOL_HANDLER_QT_H_
+#ifndef TOUCH_HANDLE_DRAWABLE_CLIENT_H
+#define TOUCH_HANDLE_DRAWABLE_CLIENT_H
-#include "net/url_request/url_request_job_factory.h"
-
-namespace net {
-
-class NetworkDelegate;
-class URLRequestJob;
-
-} // namespace
+#include "qtwebenginecoreglobal_p.h"
+#include <QRect>
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 {
-
+class QWEBENGINECORE_PRIVATE_EXPORT TouchHandleDrawableClient {
public:
- QrcProtocolHandlerQt();
- net::URLRequestJob *MaybeCreateJob(net::URLRequest *request, net::NetworkDelegate *networkDelegate) const override;
+ virtual ~TouchHandleDrawableClient() { }
-private:
- DISALLOW_COPY_AND_ASSIGN(QrcProtocolHandlerQt);
+ virtual void setImage(int orientation) = 0;
+ virtual void setBounds(const QRect &bounds) = 0;
+ virtual void setVisible(bool visible) = 0;
+ virtual void setOpacity(float opacity) = 0;
};
} // namespace QtWebEngineCore
-#endif // QRC_PROTOCOL_HANDLER_QT_H_
+#endif // TOUCH_HANDLE_DRAWABLE_CLIENT_H
diff --git a/src/core/touch_handle_drawable_qt.cpp b/src/core/touch_handle_drawable_qt.cpp
new file mode 100644
index 000000000..66b1cf40e
--- /dev/null
+++ b/src/core/touch_handle_drawable_qt.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE.Chromium file.
+
+// This implementation is based on chromium/ui/touch_selection/touch_handle_drawable_aura.cc
+
+#include "render_widget_host_view_qt.h"
+#include "touch_handle_drawable_client.h"
+#include "touch_handle_drawable_qt.h"
+#include "type_conversion.h"
+#include "web_contents_adapter_client.h"
+
+#include "ui/gfx/image/image.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/resources/grit/ui_resources.h"
+
+namespace QtWebEngineCore {
+
+namespace {
+// The distance by which a handle image is offset from the focal point (i.e.
+// text baseline) downwards.
+const int kSelectionHandleVerticalVisualOffset = 2;
+
+// The padding around the selection handle image can be used to extend the
+// handle window so that touch events near the selection handle image are
+// targeted to the selection handle window.
+const int kSelectionHandlePadding = 0;
+
+// Epsilon value used to compare float values to zero.
+const float kEpsilon = 1e-8f;
+
+// Returns the appropriate handle image based on the handle orientation.
+gfx::Image* GetHandleImage(ui::TouchHandleOrientation orientation)
+{
+ int resource_id = 0;
+ switch (orientation) {
+ case ui::TouchHandleOrientation::LEFT:
+ resource_id = IDR_TEXT_SELECTION_HANDLE_LEFT;
+ break;
+ case ui::TouchHandleOrientation::CENTER:
+ resource_id = IDR_TEXT_SELECTION_HANDLE_CENTER;
+ break;
+ case ui::TouchHandleOrientation::RIGHT:
+ resource_id = IDR_TEXT_SELECTION_HANDLE_RIGHT;
+ break;
+ case ui::TouchHandleOrientation::UNDEFINED:
+ NOTREACHED() << "Invalid touch handle bound type.";
+ return nullptr;
+ };
+ return &ui::ResourceBundle::GetSharedInstance().GetImageNamed(resource_id);
+}
+
+bool IsNearlyZero(float value)
+{
+ return std::abs(value) < kEpsilon;
+}
+
+} // namespace
+
+TouchHandleDrawableQt::TouchHandleDrawableQt(RenderWidgetHostViewQt *rwhv)
+ : m_rwhv(rwhv)
+ , m_enabled(false)
+ , m_alpha(0)
+ , m_orientation(ui::TouchHandleOrientation::UNDEFINED)
+{
+ QMap<int, QImage> images;
+ for (int orientation = 0; orientation < static_cast<int>(ui::TouchHandleOrientation::UNDEFINED); ++orientation) {
+ gfx::Image* image = GetHandleImage(static_cast<ui::TouchHandleOrientation>(orientation));
+ images.insert(orientation, toQImage(image->AsBitmap()));
+ }
+
+ Q_ASSERT(m_rwhv);
+ Q_ASSERT(m_rwhv->adapterClient());
+ m_client.reset(m_rwhv->adapterClient()->createTouchHandle(images));
+}
+
+TouchHandleDrawableQt::~TouchHandleDrawableQt()
+{
+}
+
+void TouchHandleDrawableQt::UpdateBounds()
+{
+ if (!m_client)
+ return;
+
+ gfx::RectF newBounds = m_relativeBounds;
+ newBounds.Offset(m_originPosition.x(), m_originPosition.y());
+ m_client->setBounds(toQt(gfx::ToEnclosingRect(newBounds)));
+}
+
+bool TouchHandleDrawableQt::IsVisible() const
+{
+ return m_enabled && !IsNearlyZero(m_alpha);
+}
+
+void TouchHandleDrawableQt::SetEnabled(bool enabled)
+{
+ if (!m_client)
+ return;
+
+ if (enabled == m_enabled)
+ return;
+
+ m_enabled = enabled;
+ m_client->setVisible(enabled);
+}
+
+void TouchHandleDrawableQt::SetOrientation(ui::TouchHandleOrientation orientation, bool mirror_vertical, bool mirror_horizontal)
+{
+ if (!m_client)
+ return;
+
+ // TODO: Implement adaptive handle orientation logic
+ DCHECK(!mirror_vertical);
+ DCHECK(!mirror_horizontal);
+
+ if (m_orientation == orientation)
+ return;
+ m_orientation = orientation;
+ gfx::Image* image = GetHandleImage(orientation);
+ m_client->setImage(static_cast<int>(orientation));
+
+ // Calculate the relative bounds.
+ gfx::Size image_size = image->Size();
+ int window_width = image_size.width() + 2 * kSelectionHandlePadding;
+ int window_height = image_size.height() + 2 * kSelectionHandlePadding;
+ m_relativeBounds =
+ gfx::RectF(-kSelectionHandlePadding,
+ kSelectionHandleVerticalVisualOffset - kSelectionHandlePadding,
+ window_width, window_height);
+ UpdateBounds();
+}
+
+void TouchHandleDrawableQt::SetOrigin(const gfx::PointF& position)
+{
+ m_originPosition = position;
+ UpdateBounds();
+}
+
+void TouchHandleDrawableQt::SetAlpha(float alpha)
+{
+ if (!m_client)
+ return;
+
+ if (alpha == m_alpha)
+ return;
+
+ m_alpha = alpha;
+ m_client->setOpacity(m_alpha);
+ m_client->setVisible(IsVisible());
+}
+
+gfx::RectF TouchHandleDrawableQt::GetVisibleBounds() const
+{
+ gfx::RectF bounds = m_relativeBounds;
+ bounds.Offset(m_originPosition.x(), m_originPosition.y());
+
+ gfx::RectF visibleBounds(bounds);
+ visibleBounds.Inset(kSelectionHandlePadding,
+ kSelectionHandlePadding + kSelectionHandleVerticalVisualOffset,
+ kSelectionHandlePadding,
+ kSelectionHandlePadding);
+ return visibleBounds;
+}
+
+float TouchHandleDrawableQt::GetDrawableHorizontalPaddingRatio() const
+{
+ // Qt does not have any transparent padding for its handle drawable.
+ return 0.0;
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/touch_handle_drawable_qt.h b/src/core/touch_handle_drawable_qt.h
new file mode 100644
index 000000000..46fa217b7
--- /dev/null
+++ b/src/core/touch_handle_drawable_qt.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOUCH_HANDLE_DRAWABLE_QT_H
+#define TOUCH_HANDLE_DRAWABLE_QT_H
+
+#include "ui/touch_selection/touch_handle.h"
+#include "ui/touch_selection/touch_handle_orientation.h"
+
+#include <QtCore/QScopedPointer>
+
+namespace QtWebEngineCore {
+
+class RenderWidgetHostViewQt;
+class TouchHandleDrawableClient;
+
+class TouchHandleDrawableQt : public ui::TouchHandleDrawable
+{
+public:
+ explicit TouchHandleDrawableQt(RenderWidgetHostViewQt *rwhv);
+ ~TouchHandleDrawableQt() override;
+
+private:
+ void UpdateBounds();
+ bool IsVisible() const;
+
+ // ui::TouchHandleDrawable overrides
+ void SetEnabled(bool enabled) override;
+ void SetOrientation(ui::TouchHandleOrientation orientation,
+ bool mirror_vertical,
+ bool mirror_horizontal) override;
+ void SetOrigin(const gfx::PointF& position) override;
+ void SetAlpha(float alpha) override;
+ gfx::RectF GetVisibleBounds() const override;
+ float GetDrawableHorizontalPaddingRatio() const override;
+
+ RenderWidgetHostViewQt *m_rwhv;
+ QScopedPointer<TouchHandleDrawableClient> m_client;
+
+ bool m_enabled;
+ float m_alpha;
+ ui::TouchHandleOrientation m_orientation;
+ gfx::RectF m_relativeBounds;
+ gfx::PointF m_originPosition;
+
+ DISALLOW_COPY_AND_ASSIGN(TouchHandleDrawableQt);
+};
+
+} // namespace QtWebEngineCore
+
+#endif // TOUCH_HANDLE_DRAWABLE_QT_H
diff --git a/src/core/touch_selection_controller_client_qt.cpp b/src/core/touch_selection_controller_client_qt.cpp
new file mode 100644
index 000000000..da3c78b8a
--- /dev/null
+++ b/src/core/touch_selection_controller_client_qt.cpp
@@ -0,0 +1,343 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "render_widget_host_view_qt.h"
+#include "touch_handle_drawable_qt.h"
+#include "touch_selection_controller_client_qt.h"
+#include "touch_selection_menu_controller.h"
+#include "type_conversion.h"
+#include "web_contents_adapter.h"
+#include "web_contents_adapter_client.h"
+
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "ui/gfx/geometry/size_conversions.h"
+
+#include <QClipboard>
+#include <QGuiApplication>
+
+namespace QtWebEngineCore {
+
+TouchSelectionControllerClientQt::TouchSelectionControllerClientQt(RenderWidgetHostViewQt *rwhv)
+ : m_rwhv(rwhv)
+ , m_menuController(new TouchSelectionMenuController(this))
+ , m_menuShowing(false)
+ , m_menuRequested(false)
+ , m_touchDown(false)
+ , m_scrollInProgress(false)
+ , m_handleDragInProgress(false)
+{
+ Q_ASSERT(rwhv);
+}
+
+TouchSelectionControllerClientQt::~TouchSelectionControllerClientQt()
+{
+}
+
+bool TouchSelectionControllerClientQt::handleContextMenu(const content::ContextMenuParams& params)
+{
+ if ((params.source_type == ui::MENU_SOURCE_LONG_PRESS ||
+ params.source_type == ui::MENU_SOURCE_LONG_TAP) &&
+ params.is_editable && params.selection_text.empty()) {
+ m_menuRequested = true;
+ updateMenu();
+ return true;
+ }
+
+ const bool from_touch = params.source_type == ui::MENU_SOURCE_LONG_PRESS ||
+ params.source_type == ui::MENU_SOURCE_LONG_TAP ||
+ params.source_type == ui::MENU_SOURCE_TOUCH;
+ if (from_touch && !params.selection_text.empty())
+ return true;
+
+ GetTouchSelectionController()->HideAndDisallowShowingAutomatically();
+ return false;
+}
+
+void TouchSelectionControllerClientQt::onTouchDown()
+{
+ m_touchDown = true;
+ updateMenu();
+}
+
+void TouchSelectionControllerClientQt::onTouchUp()
+{
+ m_touchDown = false;
+ updateMenu();
+}
+
+void TouchSelectionControllerClientQt::onScrollBegin()
+{
+ m_scrollInProgress = true;
+ GetTouchSelectionController()->SetTemporarilyHidden(true);
+ updateMenu();
+}
+
+void TouchSelectionControllerClientQt::onScrollEnd()
+{
+ m_scrollInProgress = false;
+ GetTouchSelectionController()->SetTemporarilyHidden(false);
+ updateMenu();
+}
+
+bool TouchSelectionControllerClientQt::IsCommandIdEnabled(int command_id) const
+{
+ bool editable = m_rwhv->getTextInputType() != ui::TEXT_INPUT_TYPE_NONE;
+ bool readable = m_rwhv->getTextInputType() != ui::TEXT_INPUT_TYPE_PASSWORD;
+ bool hasSelection = !m_rwhv->GetSelectedText().empty();
+
+ switch (command_id) {
+ case TouchSelectionMenuController::Cut:
+ return editable && readable && hasSelection;
+ case TouchSelectionMenuController::Copy:
+ return readable && hasSelection;
+ case TouchSelectionMenuController::Paste:
+ return editable && !QGuiApplication::clipboard()->text().isEmpty();
+ default:
+ return false;
+ }
+}
+
+void TouchSelectionControllerClientQt::ExecuteCommand(int command_id, int event_flags)
+{
+ Q_UNUSED(event_flags);
+ GetTouchSelectionController()->HideAndDisallowShowingAutomatically();
+
+ WebContentsAdapterClient *adapterClient = m_rwhv->adapterClient();
+ Q_ASSERT(adapterClient);
+ WebContentsAdapter *adapter = adapterClient->webContentsAdapter();
+ Q_ASSERT(adapter);
+
+ switch (command_id) {
+ case TouchSelectionMenuController::Cut:
+ adapter->cut();
+ break;
+ case TouchSelectionMenuController::Copy:
+ adapter->copy();
+ break;
+ case TouchSelectionMenuController::Paste:
+ adapter->paste();
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void TouchSelectionControllerClientQt::RunContextMenu()
+{
+ gfx::RectF anchorRect = GetTouchSelectionController()->GetRectBetweenBounds();
+ gfx::PointF anchorPoint = gfx::PointF(anchorRect.CenterPoint().x(), anchorRect.y());
+
+ content::RenderWidgetHostImpl *host = m_rwhv->host();
+ host->ShowContextMenuAtPoint(gfx::ToRoundedPoint(anchorPoint),
+ ui::MENU_SOURCE_TOUCH_EDIT_MENU);
+
+ // Hide selection handles after getting rect-between-bounds from touch
+ // selection controller; otherwise, rect would be empty and the above
+ // calculations would be invalid.
+ GetTouchSelectionController()->HideAndDisallowShowingAutomatically();
+}
+
+void TouchSelectionControllerClientQt::DidStopFlinging()
+{
+ onScrollEnd();
+}
+
+void TouchSelectionControllerClientQt::UpdateClientSelectionBounds(const gfx::SelectionBound& start,
+ const gfx::SelectionBound& end)
+{
+ UpdateClientSelectionBounds(start, end, this, this);
+}
+
+void TouchSelectionControllerClientQt::UpdateClientSelectionBounds(const gfx::SelectionBound& start,
+ const gfx::SelectionBound& end,
+ ui::TouchSelectionControllerClient* client,
+ ui::TouchSelectionMenuClient* menu_client)
+{
+ Q_UNUSED(client);
+ Q_UNUSED(menu_client);
+
+ GetTouchSelectionController()->OnSelectionBoundsChanged(start, end);
+}
+
+void TouchSelectionControllerClientQt::InvalidateClient(ui::TouchSelectionControllerClient* client)
+{
+ Q_UNUSED(client);
+}
+
+ui::TouchSelectionController* TouchSelectionControllerClientQt::GetTouchSelectionController()
+{
+ return m_rwhv->getTouchSelectionController();
+}
+
+void TouchSelectionControllerClientQt::AddObserver(Observer* observer)
+{
+ Q_UNUSED(observer);
+}
+
+void TouchSelectionControllerClientQt::RemoveObserver(Observer* observer)
+{
+ Q_UNUSED(observer);
+}
+
+bool TouchSelectionControllerClientQt::SupportsAnimation() const
+{
+ return false;
+}
+
+void TouchSelectionControllerClientQt::SetNeedsAnimate()
+{
+ NOTREACHED();
+}
+
+void TouchSelectionControllerClientQt::MoveCaret(const gfx::PointF& position)
+{
+ content::mojom::FrameInputHandler *frameInputHandler = m_rwhv->getFrameInputHandler();
+ if (!frameInputHandler)
+ return;
+
+ frameInputHandler->MoveCaret(gfx::ToRoundedPoint(position));
+}
+
+void TouchSelectionControllerClientQt::MoveRangeSelectionExtent(const gfx::PointF& extent)
+{
+ content::mojom::FrameInputHandler *frameInputHandler = m_rwhv->getFrameInputHandler();
+ if (!frameInputHandler)
+ return;
+
+ frameInputHandler->MoveRangeSelectionExtent(gfx::ToRoundedPoint(extent));
+}
+
+void TouchSelectionControllerClientQt::SelectBetweenCoordinates(const gfx::PointF& base, const gfx::PointF& extent)
+{
+ content::mojom::FrameInputHandler *frameInputHandler = m_rwhv->getFrameInputHandler();
+ if (!frameInputHandler)
+ return;
+
+ frameInputHandler->SelectRange(gfx::ToRoundedPoint(base), gfx::ToRoundedPoint(extent));
+}
+
+void TouchSelectionControllerClientQt::OnSelectionEvent(ui::SelectionEventType event)
+{
+ switch (event) {
+ case ui::SELECTION_HANDLES_SHOWN:
+ m_menuRequested = true;
+ break;
+ case ui::INSERTION_HANDLE_SHOWN:
+ break;
+ case ui::SELECTION_HANDLES_CLEARED:
+ case ui::INSERTION_HANDLE_CLEARED:
+ m_menuRequested = false;
+ break;
+ case ui::SELECTION_HANDLE_DRAG_STARTED:
+ case ui::INSERTION_HANDLE_DRAG_STARTED:
+ m_handleDragInProgress = true;
+ break;
+ case ui::SELECTION_HANDLE_DRAG_STOPPED:
+ case ui::INSERTION_HANDLE_DRAG_STOPPED:
+ m_handleDragInProgress = false;
+ break;
+ case ui::SELECTION_HANDLES_MOVED:
+ case ui::INSERTION_HANDLE_MOVED:
+ break;
+ case ui::INSERTION_HANDLE_TAPPED:
+ m_menuRequested = !m_menuRequested;
+ break;
+ }
+
+ updateMenu();
+}
+
+void TouchSelectionControllerClientQt::OnDragUpdate(const gfx::PointF& position)
+{
+ Q_UNUSED(position);
+}
+
+std::unique_ptr<ui::TouchHandleDrawable> TouchSelectionControllerClientQt::CreateDrawable()
+{
+ return std::unique_ptr<ui::TouchHandleDrawable>(new TouchHandleDrawableQt(m_rwhv));
+}
+
+void TouchSelectionControllerClientQt::DidScroll()
+{
+}
+
+void TouchSelectionControllerClientQt::showMenu()
+{
+ gfx::RectF rect = GetTouchSelectionController()->GetRectBetweenBounds();
+ gfx::PointF origin = rect.origin();
+ gfx::PointF bottom_right = rect.bottom_right();
+
+ gfx::Vector2dF diagonal = bottom_right - origin;
+ gfx::SizeF size(diagonal.x(), diagonal.y());
+ gfx::RectF anchor_rect(origin, size);
+
+ // Calculate maximum handle image size;
+ gfx::SizeF max_handle_size = GetTouchSelectionController()->GetStartHandleRect().size();
+ max_handle_size.SetToMax(GetTouchSelectionController()->GetEndHandleRect().size());
+
+ WebContentsAdapterClient *adapterClient = m_rwhv->adapterClient();
+ Q_ASSERT(adapterClient);
+ adapterClient->showTouchSelectionMenu(m_menuController.get(),
+ QRect(toQt(gfx::ToEnclosingRect(anchor_rect))),
+ QSize(toQt(gfx::ToRoundedSize(max_handle_size))));
+ m_menuShowing = true;
+}
+
+void TouchSelectionControllerClientQt::hideMenu()
+{
+ WebContentsAdapterClient *adapterClient = m_rwhv->adapterClient();
+ Q_ASSERT(adapterClient);
+ adapterClient->hideTouchSelectionMenu();
+ m_menuShowing = false;
+}
+
+void TouchSelectionControllerClientQt::updateMenu()
+{
+ if (m_menuShowing)
+ hideMenu();
+
+ if (m_menuRequested && !m_touchDown &&
+ !m_scrollInProgress && !m_handleDragInProgress) {
+ showMenu();
+ }
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/touch_selection_controller_client_qt.h b/src/core/touch_selection_controller_client_qt.h
new file mode 100644
index 000000000..cdc45cac3
--- /dev/null
+++ b/src/core/touch_selection_controller_client_qt.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOUCH_SELECTION_CONTROLLER_CLIENT_QT_H
+#define TOUCH_SELECTION_CONTROLLER_CLIENT_QT_H
+
+#include "content/public/browser/touch_selection_controller_client_manager.h"
+#include "content/public/common/context_menu_params.h"
+#include "ui/touch_selection/touch_selection_controller.h"
+#include "ui/touch_selection/touch_selection_menu_runner.h"
+
+#include <QtCore/QScopedPointer>
+
+namespace QtWebEngineCore {
+
+class RenderWidgetHostViewQt;
+class TouchSelectionMenuController;
+
+class TouchSelectionControllerClientQt
+ : public ui::TouchSelectionControllerClient
+ , public ui::TouchSelectionMenuClient
+ , public content::TouchSelectionControllerClientManager
+{
+public:
+ explicit TouchSelectionControllerClientQt(RenderWidgetHostViewQt *rwhv);
+ ~TouchSelectionControllerClientQt() override;
+
+ void UpdateClientSelectionBounds(const gfx::SelectionBound& start,
+ const gfx::SelectionBound& end);
+ bool handleContextMenu(const content::ContextMenuParams& params);
+ void onTouchDown();
+ void onTouchUp();
+ void onScrollBegin();
+ void onScrollEnd();
+
+ // ui::TouchSelectionMenuClient overrides
+ bool IsCommandIdEnabled(int command_id) const override;
+ void ExecuteCommand(int command_id, int event_flags) override;
+ void RunContextMenu() override;
+
+ // content::TouchSelectionControllerClientManager overrides
+ void DidStopFlinging() override;
+ void UpdateClientSelectionBounds(const gfx::SelectionBound& start,
+ const gfx::SelectionBound& end,
+ ui::TouchSelectionControllerClient* client,
+ ui::TouchSelectionMenuClient* menu_client) override;
+ void InvalidateClient(ui::TouchSelectionControllerClient* client) override;
+ ui::TouchSelectionController* GetTouchSelectionController() override;
+ void AddObserver(Observer* observer) override;
+ void RemoveObserver(Observer* observer) override;
+
+ // ui::TouchSelectionControllerClient overrides
+ bool SupportsAnimation() const override;
+ void SetNeedsAnimate() override;
+ void MoveCaret(const gfx::PointF& position) override;
+ void MoveRangeSelectionExtent(const gfx::PointF& extent) override;
+ void SelectBetweenCoordinates(const gfx::PointF& base, const gfx::PointF& extent) override;
+ void OnSelectionEvent(ui::SelectionEventType event) override;
+ void OnDragUpdate(const gfx::PointF& position) override;
+ std::unique_ptr<ui::TouchHandleDrawable> CreateDrawable() override;
+ void DidScroll() override;
+
+private:
+ void showMenu();
+ void hideMenu();
+ void updateMenu();
+
+ RenderWidgetHostViewQt *m_rwhv;
+ QScopedPointer<TouchSelectionMenuController> m_menuController;
+
+ bool m_menuShowing;
+ bool m_menuRequested;
+ bool m_touchDown;
+ bool m_scrollInProgress;
+ bool m_handleDragInProgress;
+};
+
+} // namespace QtWebEngineCore
+
+#endif // TOUCH_SELECTION_CONTROLLER_CLIENT_QT_H
diff --git a/src/core/touch_selection_menu_controller.cpp b/src/core/touch_selection_menu_controller.cpp
new file mode 100644
index 000000000..cdec9a064
--- /dev/null
+++ b/src/core/touch_selection_menu_controller.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "touch_selection_controller_client_qt.h"
+#include "touch_selection_menu_controller.h"
+
+namespace QtWebEngineCore {
+
+TouchSelectionMenuController::TouchSelectionMenuController(TouchSelectionControllerClientQt *touchSelectionControllerClient)
+ : m_touchSelectionControllerClient(touchSelectionControllerClient)
+{
+}
+
+TouchSelectionMenuController::~TouchSelectionMenuController()
+{
+}
+
+int TouchSelectionMenuController::buttonCount()
+{
+ int buttonCount = 1;
+
+ for (int commandId = 0; commandId <= static_cast<int>(Paste); ++commandId) {
+ if (m_touchSelectionControllerClient->IsCommandIdEnabled(commandId))
+ buttonCount++;
+ }
+
+ return buttonCount;
+}
+
+bool TouchSelectionMenuController::isCommandEnabled(TouchSelectionCommand command)
+{
+ return m_touchSelectionControllerClient->IsCommandIdEnabled(static_cast<int>(command));
+}
+
+void TouchSelectionMenuController::cut()
+{
+ m_touchSelectionControllerClient->ExecuteCommand(static_cast<int>(Cut), 0);
+}
+
+void TouchSelectionMenuController::copy()
+{
+ m_touchSelectionControllerClient->ExecuteCommand(static_cast<int>(Copy), 0);
+}
+
+void TouchSelectionMenuController::paste()
+{
+ m_touchSelectionControllerClient->ExecuteCommand(static_cast<int>(Paste), 0);
+}
+
+void TouchSelectionMenuController::runContextMenu()
+{
+ return m_touchSelectionControllerClient->RunContextMenu();
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/touch_selection_menu_controller.h b/src/core/touch_selection_menu_controller.h
new file mode 100644
index 000000000..fd61ae709
--- /dev/null
+++ b/src/core/touch_selection_menu_controller.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef TOUCH_SELECTION_MENU_CONTROLLER_H
+#define TOUCH_SELECTION_MENU_CONTROLLER_H
+
+#include "qtwebenginecoreglobal_p.h"
+#include <QtCore/QObject>
+
+namespace QtWebEngineCore {
+
+class TouchSelectionControllerClientQt;
+
+class QWEBENGINECORE_PRIVATE_EXPORT TouchSelectionMenuController : public QObject {
+ Q_OBJECT
+public:
+ enum TouchSelectionCommand {
+ Cut,
+ Copy,
+ Paste
+ };
+
+ TouchSelectionMenuController(TouchSelectionControllerClientQt *touchSelectionControllerClient);
+ ~TouchSelectionMenuController();
+ int buttonCount();
+ bool isCommandEnabled(TouchSelectionCommand);
+
+public Q_SLOTS:
+ void cut();
+ void copy();
+ void paste();
+ void runContextMenu();
+
+private:
+ TouchSelectionControllerClientQt *m_touchSelectionControllerClient;
+};
+
+} // namespace QtWebEngineCore
+
+#endif // TOUCH_SELECTION_CONTROLLER_CLIENT_QT_H
diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp
index d35426ac3..ef16e2add 100644
--- a/src/core/type_conversion.cpp
+++ b/src/core/type_conversion.cpp
@@ -42,7 +42,9 @@
#include <content/public/common/favicon_url.h>
#include <ui/events/event_constants.h>
#include <ui/gfx/image/image_skia.h>
+
#include <QtCore/qcoreapplication.h>
+#include <QtGui/qmatrix4x4.h>
namespace QtWebEngineCore {
@@ -131,7 +133,7 @@ QImage toQImage(const SkBitmap &bitmap)
QImage toQImage(const gfx::ImageSkiaRep &imageSkiaRep)
{
- QImage image = toQImage(imageSkiaRep.sk_bitmap());
+ QImage image = toQImage(imageSkiaRep.GetBitmap());
if (!image.isNull() && imageSkiaRep.scale() != 1.0f)
image.setDevicePixelRatio(imageSkiaRep.scale());
return image;
@@ -243,4 +245,15 @@ FaviconInfo toFaviconInfo(const content::FaviconURL &favicon_url)
return info;
}
+void convertToQt(const SkMatrix44 &m, QMatrix4x4 &c)
+{
+ QMatrix4x4 qtMatrix(
+ m.get(0, 0), m.get(0, 1), m.get(0, 2), m.get(0, 3),
+ m.get(1, 0), m.get(1, 1), m.get(1, 2), m.get(1, 3),
+ m.get(2, 0), m.get(2, 1), m.get(2, 2), m.get(2, 3),
+ m.get(3, 0), m.get(3, 1), m.get(3, 2), m.get(3, 3));
+ qtMatrix.optimize();
+ c = qtMatrix;
+}
+
} // namespace QtWebEngineCore
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index afc3c3336..96b4ecadc 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -45,7 +45,6 @@
#include <QDir>
#include <QIcon>
#include <QImage>
-#include <QMatrix4x4>
#include <QNetworkCookie>
#include <QRect>
#include <QString>
@@ -64,6 +63,8 @@
#include "ui/gfx/geometry/rect_f.h"
#include "url/gurl.h"
+QT_FORWARD_DECLARE_CLASS(QMatrix4x4)
+
namespace content {
struct FaviconURL;
}
@@ -198,16 +199,7 @@ SkBitmap toSkBitmap(const QImage &image);
QIcon toQIcon(const std::vector<SkBitmap> &bitmaps);
-inline QMatrix4x4 toQt(const SkMatrix44 &m)
-{
- QMatrix4x4 qtMatrix(
- m.get(0, 0), m.get(0, 1), m.get(0, 2), m.get(0, 3),
- m.get(1, 0), m.get(1, 1), m.get(1, 2), m.get(1, 3),
- m.get(2, 0), m.get(2, 1), m.get(2, 2), m.get(2, 3),
- m.get(3, 0), m.get(3, 1), m.get(3, 2), m.get(3, 3));
- qtMatrix.optimize();
- return qtMatrix;
-}
+void convertToQt(const SkMatrix44 &m, QMatrix4x4 &c);
inline QDateTime toQt(base::Time time)
{
diff --git a/src/core/visited_links_manager_qt.cpp b/src/core/visited_links_manager_qt.cpp
index ac27446b8..d4885e8e8 100644
--- a/src/core/visited_links_manager_qt.cpp
+++ b/src/core/visited_links_manager_qt.cpp
@@ -39,7 +39,6 @@
#include "visited_links_manager_qt.h"
-#include "profile_adapter.h"
#include "content_browser_client_qt.h"
#include "profile_qt.h"
#include "type_conversion.h"
@@ -106,14 +105,13 @@ static void ensureDirectoryExists(const base::FilePath &path)
errorstr.c_str());
}
-VisitedLinksManagerQt::VisitedLinksManagerQt(ProfileAdapter *adapter)
+VisitedLinksManagerQt::VisitedLinksManagerQt(ProfileQt *profile, bool persistVisitedLinks)
: m_delegate(new VisitedLinkDelegateQt)
{
- Q_ASSERT(adapter && adapter->profile());
- ProfileQt *profile = adapter->profile();
- if (adapter->persistVisitedLinks())
+ Q_ASSERT(profile);
+ if (persistVisitedLinks)
ensureDirectoryExists(profile->GetPath());
- m_visitedLinkMaster.reset(new visitedlink::VisitedLinkMaster(profile, m_delegate.data(), adapter->persistVisitedLinks()));
+ m_visitedLinkMaster.reset(new visitedlink::VisitedLinkMaster(profile, m_delegate.data(), persistVisitedLinks));
m_visitedLinkMaster->Init();
}
diff --git a/src/core/visited_links_manager_qt.h b/src/core/visited_links_manager_qt.h
index 8d9a7495b..5bbcc5983 100644
--- a/src/core/visited_links_manager_qt.h
+++ b/src/core/visited_links_manager_qt.h
@@ -67,14 +67,14 @@ class GURL;
namespace QtWebEngineCore {
-class ProfileAdapter;
+class ProfileQt;
class VisitedLinkDelegateQt;
class QWEBENGINECORE_PRIVATE_EXPORT VisitedLinksManagerQt {
public:
virtual~VisitedLinksManagerQt();
- VisitedLinksManagerQt(ProfileAdapter *profileAdapter);
+ VisitedLinksManagerQt(ProfileQt *profile, bool persistVisitedLinks);
void deleteAllVisitedLinkData();
void deleteVisitedLinkDataForUrls(const QList<QUrl> &);
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 21540f5da..68bbc3daa 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -43,15 +43,14 @@
#include "web_contents_adapter.h"
-#include "browser_accessibility_qt.h"
-#include "profile_adapter_client.h"
-#include "profile_adapter.h"
#include "devtools_frontend_qt.h"
#include "download_manager_delegate_qt.h"
#include "media_capture_devices_dispatcher.h"
#if QT_CONFIG(webengine_printing_and_pdf)
#include "printing/print_view_manager_qt.h"
#endif
+#include "profile_adapter_client.h"
+#include "profile_adapter.h"
#include "profile_qt.h"
#include "qwebenginecallback_p.h"
#include "render_view_observer_host_qt.h"
@@ -63,9 +62,11 @@
#include "base/command_line.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/values.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/download_manager.h"
@@ -83,7 +84,6 @@
#include "content/public/common/url_constants.h"
#include "content/public/common/web_preferences.h"
#include "content/public/common/webrtc_ip_handling_policy.h"
-#include "third_party/blink/public/web/web_find_options.h"
#include "third_party/blink/public/web/web_media_player_action.h"
#include "printing/buildflags/buildflags.h"
#include "ui/base/clipboard/clipboard.h"
@@ -105,10 +105,14 @@
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmimedata.h>
#include <QtCore/qtemporarydir.h>
-#include <QtGui/qaccessible.h>
#include <QtGui/qdrag.h>
#include <QtGui/qpixmap.h>
+// Can't include headers as qaccessible.h conflicts with Chromium headers.
+namespace content {
+extern QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *acc);
+}
+
namespace QtWebEngineCore {
#define CHECK_INITIALIZED(return_value) \
@@ -117,7 +121,7 @@ namespace QtWebEngineCore {
#define CHECK_VALID_RENDER_WIDGET_HOST_VIEW(render_view_host) \
if (!render_view_host->IsRenderViewLive() && render_view_host->GetWidget()->GetView()) { \
- qWarning("Ignore navigation due to terminated render process with invalid RenderWidgetHostView."); \
+ LOG(WARNING) << "Ignore navigation due to terminated render process with invalid RenderWidgetHostView."; \
return; \
}
@@ -190,7 +194,7 @@ static QVariant fromJSValue(const base::Value *result)
}
case base::Value::Type::BINARY:
{
- QByteArray data(result->GetBlob().data(), result->GetBlob().size());
+ QByteArray data(reinterpret_cast<const char *>(result->GetBlob().data()), result->GetBlob().size());
ret.setValue(data);
break;
}
@@ -210,10 +214,10 @@ static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint6
#if QT_CONFIG(webengine_printing_and_pdf)
static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient,
int requestId,
- const std::vector<char>& result)
+ QSharedPointer<QByteArray> result)
{
if (requestId)
- adapterClient->didPrintPage(requestId, QByteArray(result.data(), result.size()));
+ adapterClient->didPrintPage(requestId, result);
}
static void callbackOnPdfSavingFinished(WebContentsAdapterClient *adapterClient,
@@ -662,8 +666,8 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request)
if (resizeNeeded) {
// Schedule navigation on the event loop.
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE, base::BindOnce(navigate, this, std::move(params)));
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(navigate, this, std::move(params)));
} else {
navigate(this, params);
}
@@ -800,7 +804,7 @@ void WebContentsAdapter::selectAll()
void WebContentsAdapter::requestClose()
{
CHECK_INITIALIZED();
- m_webContents->DispatchBeforeUnload();
+ m_webContents->DispatchBeforeUnload(false /* auto_cancel */);
}
void WebContentsAdapter::unselect()
@@ -932,8 +936,8 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible()
if (!manager) // FIXME!
return nullptr;
content::BrowserAccessibility *acc = manager->GetRoot();
- content::BrowserAccessibilityQt *accQt = static_cast<content::BrowserAccessibilityQt*>(acc);
- return accQt;
+
+ return content::toQAccessibleInterface(acc);
}
#endif // QT_NO_ACCESSIBILITY
@@ -990,16 +994,16 @@ quint64 WebContentsAdapter::findText(const QString &subString, bool caseSensitiv
m_adapterClient->didFindText(m_lastFindRequestId, 0);
}
- blink::WebFindOptions options;
- options.forward = !findBackward;
- options.match_case = caseSensitively;
- options.find_next = subString == m_webContentsDelegate->lastSearchedString();
+ blink::mojom::FindOptionsPtr options = blink::mojom::FindOptions::New();
+ options->forward = !findBackward;
+ options->match_case = caseSensitively;
+ options->find_next = subString == m_webContentsDelegate->lastSearchedString();
m_webContentsDelegate->setLastSearchedString(subString);
// Find already allows a request ID as input, but only as an int.
// Use the same counter but mod it to MAX_INT, this keeps the same likeliness of request ID clashing.
int shrunkRequestId = m_nextRequestId++ & 0x7fffffff;
- m_webContents->Find(shrunkRequestId, toString16(subString), options);
+ m_webContents->Find(shrunkRequestId, toString16(subString), std::move(options));
m_lastFindRequestId = shrunkRequestId;
return shrunkRequestId;
}
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 55cbe13dd..4a36e77f9 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -66,6 +66,7 @@ QT_FORWARD_DECLARE_CLASS(QKeyEvent)
QT_FORWARD_DECLARE_CLASS(QVariant)
QT_FORWARD_DECLARE_CLASS(QWebEngineQuotaRequest)
QT_FORWARD_DECLARE_CLASS(QWebEngineRegisterProtocolHandlerRequest)
+QT_FORWARD_DECLARE_CLASS(QWebEngineUrlRequestInfo)
namespace content {
struct DropData;
@@ -81,6 +82,8 @@ class JavaScriptDialogController;
class RenderWidgetHostViewQt;
class RenderWidgetHostViewQtDelegate;
class RenderWidgetHostViewQtDelegateClient;
+class TouchHandleDrawableClient;
+class TouchSelectionMenuController;
class WebContentsAdapter;
class WebContentsDelegateQt;
class WebEngineSettings;
@@ -444,7 +447,7 @@ public:
virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) = 0;
virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0;
virtual void didFindText(quint64 requestId, int matchCount) = 0;
- virtual void didPrintPage(quint64 requestId, const QByteArray &result) = 0;
+ virtual void didPrintPage(quint64 requestId, QSharedPointer<QByteArray>) = 0;
virtual void didPrintPageToPdf(const QString &filePath, bool success) = 0;
virtual void passOnFocus(bool reverse) = 0;
// returns the last QObject (QWidget/QQuickItem) based object in the accessibility
@@ -475,6 +478,10 @@ public:
virtual ClientType clientType() = 0;
virtual void printRequested() = 0;
virtual void widgetChanged(RenderWidgetHostViewQtDelegate *newWidget) = 0;
+ virtual void interceptRequest(QWebEngineUrlRequestInfo &) { }
+ virtual TouchHandleDrawableClient *createTouchHandle(const QMap<int, QImage> &images) = 0;
+ virtual void showTouchSelectionMenu(TouchSelectionMenuController *menuController, const QRect &bounds, const QSize &handleSize) = 0;
+ virtual void hideTouchSelectionMenu() = 0;
virtual ProfileAdapter *profileAdapter() = 0;
virtual WebContentsAdapter* webContentsAdapter() = 0;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 4bde93fd3..963b89a3f 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -65,6 +65,7 @@
#include "components/web_cache/browser/web_cache_manager.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
@@ -73,7 +74,6 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/favicon_url.h"
-#include "content/public/common/file_chooser_params.h"
#include "content/public/common/frame_navigate_params.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/web_preferences.h"
@@ -451,12 +451,14 @@ bool WebContentsDelegateQt::IsFullscreenForTabOrPending(const content::WebConten
return m_viewClient->isFullScreenMode();
}
-ASSERT_ENUMS_MATCH(FilePickerController::Open, content::FileChooserParams::Open)
-ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, content::FileChooserParams::OpenMultiple)
-ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, content::FileChooserParams::UploadFolder)
-ASSERT_ENUMS_MATCH(FilePickerController::Save, content::FileChooserParams::Save)
+ASSERT_ENUMS_MATCH(FilePickerController::Open, blink::mojom::FileChooserParams::Mode::kOpen)
+ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, blink::mojom::FileChooserParams::Mode::kOpenMultiple)
+ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, blink::mojom::FileChooserParams::Mode::kUploadFolder)
+ASSERT_ENUMS_MATCH(FilePickerController::Save, blink::mojom::FileChooserParams::Mode::kSave)
-void WebContentsDelegateQt::RunFileChooser(content::RenderFrameHost *frameHost, const content::FileChooserParams &params)
+void WebContentsDelegateQt::RunFileChooser(content::RenderFrameHost * /*frameHost*/,
+ std::unique_ptr<content::FileSelectListener> listener,
+ const blink::mojom::FileChooserParams& params)
{
QStringList acceptedMimeTypes;
acceptedMimeTypes.reserve(params.accept_types.size());
@@ -464,7 +466,7 @@ void WebContentsDelegateQt::RunFileChooser(content::RenderFrameHost *frameHost,
acceptedMimeTypes.append(toQt(*it));
m_filePickerController.reset(new FilePickerController(static_cast<FilePickerController::FileChooserMode>(params.mode),
- frameHost, toQt(params.default_file_name.value()), acceptedMimeTypes));
+ std::move(listener), toQt(params.default_file_name.value()), acceptedMimeTypes));
// Defer the call to not block base::MessageLoop::RunTask with modal dialogs.
QTimer::singleShot(0, [this] () {
@@ -633,7 +635,9 @@ void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool pr
m_viewClient->windowCloseRejected();
}
-void WebContentsDelegateQt::BeforeUnloadFired(const base::TimeTicks &proceed_time) {
+void WebContentsDelegateQt::BeforeUnloadFired(bool proceed, const base::TimeTicks &proceed_time)
+{
+ Q_UNUSED(proceed);
Q_UNUSED(proceed_time);
}
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index 9c0f8f484..40f585767 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -114,7 +114,9 @@ public:
void EnterFullscreenModeForTab(content::WebContents *web_contents, const GURL &origin, const blink::WebFullscreenOptions &) override;
void ExitFullscreenModeForTab(content::WebContents*) override;
bool IsFullscreenForTabOrPending(const content::WebContents* web_contents) const override;
- void RunFileChooser(content::RenderFrameHost* render_frame_host, const content::FileChooserParams& params) override;
+ void RunFileChooser(content::RenderFrameHost* render_frame_host,
+ std::unique_ptr<content::FileSelectListener> listener,
+ const blink::mojom::FileChooserParams& params) override;
bool DidAddMessageToConsole(content::WebContents* source, int32_t level, const base::string16& message, int32_t line_no, const base::string16& source_id) override;
void FindReply(content::WebContents *source, int request_id, int number_of_matches, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update) override;
void RequestMediaAccessPermission(content::WebContents *web_contents,
@@ -135,7 +137,7 @@ public:
void DidFinishNavigation(content::NavigationHandle *navigation_handle) override;
void DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description) override;
void DidFinishLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url) override;
- void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
+ void BeforeUnloadFired(bool proceed, const base::TimeTicks& proceed_time) override;
void DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates) override;
void OnVisibilityChanged(content::Visibility visibility) override;
void DidFirstVisuallyNonEmptyPaint() override;
diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp
index 3c4465ae3..648e0fd8f 100644
--- a/src/core/web_contents_view_qt.cpp
+++ b/src/core/web_contents_view_qt.cpp
@@ -41,18 +41,22 @@
#include "profile_adapter.h"
#include "content_browser_client_qt.h"
+#include "render_widget_host_view_qt.h"
#include "render_widget_host_view_qt_delegate.h"
#include "render_widget_host_view_qt.h"
+#include "touch_selection_controller_client_qt.h"
#include "type_conversion.h"
+#include "web_contents_adapter_client.h"
#include "web_contents_adapter.h"
#include "web_engine_context.h"
+#include "web_contents_delegate_qt.h"
#include "components/spellcheck/spellcheck_buildflags.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/context_menu_params.h"
-#include <ui/gfx/image/image_skia.h>
+#include "ui/gfx/image/image_skia.h"
#include <QtGui/qpixmap.h>
@@ -82,7 +86,7 @@ content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForWidget(conten
return view;
}
-content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForPopupWidget(content::RenderWidgetHost* render_widget_host)
+content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForChildWidget(content::RenderWidgetHost* render_widget_host)
{
RenderWidgetHostViewQt *view = new RenderWidgetHostViewQt(render_widget_host);
@@ -186,6 +190,11 @@ static inline WebEngineContextMenuData fromParams(const content::ContextMenuPara
void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const content::ContextMenuParams &params)
{
+ if (auto rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) {
+ if (rwhv && rwhv->getTouchSelectionControllerClient()->handleContextMenu(params))
+ return;
+ }
+
WebEngineContextMenuData contextMenuData(fromParams(params));
#if QT_CONFIG(webengine_spellchecker)
// Do not use params.spellcheck_enabled, since it is never
diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h
index d1a2ff81e..c7bac1d97 100644
--- a/src/core/web_contents_view_qt.h
+++ b/src/core/web_contents_view_qt.h
@@ -63,7 +63,6 @@ public:
: m_webContents(webContents)
, m_client(nullptr)
, m_factoryClient(nullptr)
- , m_allowOtherViews(false)
{ }
void initialize(WebContentsAdapterClient* client);
@@ -73,7 +72,7 @@ public:
void CreateView(const gfx::Size& initial_size, gfx::NativeView context) override;
- content::RenderWidgetHostViewBase* CreateViewForPopupWidget(content::RenderWidgetHost* render_widget_host) override;
+ content::RenderWidgetHostViewBase *CreateViewForChildWidget(content::RenderWidgetHost* render_widget_host) override;
void SetPageTitle(const base::string16& title) override { }
@@ -83,29 +82,29 @@ public:
void RenderViewHostChanged(content::RenderViewHost*, content::RenderViewHost*) override { }
- void SetOverscrollControllerEnabled(bool enabled) override { QT_NOT_YET_IMPLEMENTED }
+ void SetOverscrollControllerEnabled(bool enabled) override { }
gfx::NativeView GetNativeView() const override;
- gfx::NativeView GetContentNativeView() const override { QT_NOT_USED return 0; }
+ gfx::NativeView GetContentNativeView() const override { return 0; }
- gfx::NativeWindow GetTopLevelNativeWindow() const override { QT_NOT_USED return 0; }
+ gfx::NativeWindow GetTopLevelNativeWindow() const override { return 0; }
void GetContainerBounds(gfx::Rect* out) const override;
- void SizeContents(const gfx::Size& size) override { QT_NOT_YET_IMPLEMENTED }
+ void SizeContents(const gfx::Size& size) override { }
void Focus() override;
void SetInitialFocus() override;
- void StoreFocus() override { QT_NOT_USED }
+ void StoreFocus() override { }
- void RestoreFocus() override { QT_NOT_USED }
+ void RestoreFocus() override { }
content::DropData* GetDropData() const override { QT_NOT_YET_IMPLEMENTED return nullptr; }
- gfx::Rect GetViewBounds() const override { QT_NOT_YET_IMPLEMENTED return gfx::Rect(); }
+ gfx::Rect GetViewBounds() const override { return gfx::Rect(); }
void StartDragging(const content::DropData& drop_data, blink::WebDragOperationsMask allowed_ops,
const gfx::ImageSkia& image, const gfx::Vector2d& image_offset,
@@ -122,8 +121,6 @@ public:
#if defined(OS_MACOSX)
- void SetAllowOtherViews(bool allow) override { m_allowOtherViews = allow; }
- bool GetAllowOtherViews() const override { return m_allowOtherViews; }
void CloseTabAfterEventTracking() override { QT_NOT_YET_IMPLEMENTED }
bool IsEventTracking() const override { QT_NOT_YET_IMPLEMENTED; return false; }
#endif // defined(OS_MACOSX)
@@ -132,7 +129,6 @@ private:
content::WebContents *m_webContents;
WebContentsAdapterClient *m_client;
WebContentsAdapterClient *m_factoryClient;
- bool m_allowOtherViews;
};
} // namespace QtWebEngineCore
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index ca52a5e67..a357196b0 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -46,6 +46,7 @@
#include "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "cc/base/switches.h"
#if QT_CONFIG(webengine_printing_and_pdf)
@@ -54,13 +55,13 @@
#include "components/viz/common/features.h"
#include "components/web_cache/browser/web_cache_manager.h"
#include "content/browser/devtools/devtools_http_handler.h"
-#include "content/browser/gpu/gpu_main_thread_factory.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/utility_process_host.h"
-#include "content/gpu/in_process_gpu_thread.h"
+#include "content/browser/scheduler/browser_task_executor.h"
+#include "content/browser/startup_helper.h"
#include "content/public/app/content_main.h"
#include "content/public/app/content_main_runner.h"
#include "content/public/browser/browser_main_runner.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -68,9 +69,8 @@
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
-#include "content/renderer/in_process_renderer_thread.h"
-#include "content/utility/in_process_utility_thread.h"
#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/command_buffer/service/sync_point_manager.h"
#include "gpu/ipc/host/gpu_switches.h"
#include "media/audio/audio_manager.h"
#include "mojo/core/embedder/embedder.h"
@@ -86,20 +86,24 @@
#include "content/public/app/sandbox_helper_win.h"
#endif // OS_WIN
+#ifndef QT_NO_ACCESSIBILITY
+#include "accessibility_activation_observer.h"
+#endif
#include "api/qwebengineurlscheme.h"
-#include "profile_adapter.h"
#include "content_browser_client_qt.h"
#include "content_client_qt.h"
#include "content_main_delegate_qt.h"
#include "devtools_manager_delegate_qt.h"
#include "media_capture_devices_dispatcher.h"
#include "net/webui_controller_factory_qt.h"
-#include "type_conversion.h"
#include "ozone/gl_context_qt.h"
+#include "profile_adapter.h"
+#include "type_conversion.h"
#include "web_engine_library_info.h"
#include <QFileInfo>
#include <QGuiApplication>
+#include <QMutex>
#include <QOffscreenSurface>
#ifndef QT_NO_OPENGL
# include <QOpenGLContext>
@@ -166,6 +170,8 @@ void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&)
namespace QtWebEngineCore {
+extern std::unique_ptr<base::MessagePump> messagePumpFactory();
+
bool usingSoftwareDynamicGL()
{
if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL))
@@ -224,6 +230,12 @@ void WebEngineContext::destroy()
{
if (m_devtoolsServer)
m_devtoolsServer->stop();
+
+ // Normally the GPU thread is shut down when the GpuProcessHost is destroyed
+ // on IO thread (triggered by ~BrowserMainRunner). But by that time the UI
+ // task runner is not working anymore so we need to do this earlier.
+ destroyGpuProcess();
+
base::MessagePump::Delegate *delegate =
static_cast<base::MessageLoop *>(m_runLoop->delegate_);
// Flush the UI message loop before quitting.
@@ -273,6 +285,7 @@ WebEngineContext::~WebEngineContext()
Q_ASSERT(!m_devtoolsServer);
Q_ASSERT(!m_browserRunner);
Q_ASSERT(m_profileAdapters.isEmpty());
+ delete s_syncPointManager.fetchAndStoreRelaxed(nullptr);
}
WebEngineContext *WebEngineContext::current()
@@ -312,7 +325,7 @@ void WebEngineContext::destroyContextPostRoutine()
// Destroy WebEngineContext before its static pointer is zeroed and destructor called.
// Before destroying MessageLoop via destroying BrowserMainRunner destructor
// WebEngineContext's pointer is used.
- m_handle->destroy();
+ m_handle->destroy();
#if !defined(NDEBUG)
if (!m_handle->HasOneRef())
qWarning("WebEngineContext leaked on exit, likely due to leaked WebEngine View or Page");
@@ -421,8 +434,6 @@ WebEngineContext::WebEngineContext()
parsedCommandLine->AppendSwitch(switches::kDisablePepper3DImageChromium);
// Same problem with select popups.
parsedCommandLine->AppendSwitch(switches::kDisableNativeGpuMemoryBuffers);
- // SandboxV2 doesn't currently work for us
- appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kMacV2Sandbox.name);
#endif
#if defined(Q_OS_WIN)
@@ -430,10 +441,23 @@ WebEngineContext::WebEngineContext()
// an OpenGL Core Profile context. If the switch is not set, it would always try to create a
// Core Profile context, even if Qt uses a legacy profile, which causes
// "Could not share GL contexts" warnings, because it's not possible to share between Core and
- // legacy profiles.
- // Given that Core profile is not currently supported on Windows anyway, pass this switch to
- // get rid of the warnings.
- parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext);
+ // legacy profiles. See GLContextWGL::Initialize().
+ // Given that Desktop GL Core profile is not currently supported on Windows anyway, pass this
+ // switch to get rid of the warnings.
+ //
+ // The switch is also used to determine which version of OpenGL ES to use (2 or 3) when using
+ // ANGLE.
+ // If the switch is not set, Chromium will always try to create an ES3 context, even if Qt uses
+ // an ES2 context, which causes resource sharing issues (black screen),
+ // see gpu::gles2::GenerateGLContextAttribs().
+ // Make sure to disable ES3 context creation when using ES2.
+ const bool isGLES2Context = qt_gl_global_share_context()
+ && qt_gl_global_share_context()->isOpenGLES()
+ && qt_gl_global_share_context()->format().majorVersion() == 2;
+ const bool isDesktopGLOrSoftware = !usingANGLE();
+
+ if (isDesktopGLOrSoftware || isGLES2Context)
+ parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext);
#endif
// Needed to allow navigations within pages that were set using setHtml(). One example is
// tst_QWebEnginePage::acceptNavigationRequest.
@@ -444,8 +468,8 @@ WebEngineContext::WebEngineContext()
appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kEnableSurfaceSynchronization.name);
// The video-capture service is not functioning at this moment (since 69)
appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kMojoVideoCapture.name);
- // We do not yet support the internal video capture API.
- appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kUseVideoCaptureApiForDevToolsSnapshots.name);
+
+ appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, features::kBackgroundFetch.name);
if (useEmbeddedSwitches) {
// embedded switches are based on the switches for Android, see content/browser/android/content_startup_flags.cc
@@ -466,8 +490,7 @@ WebEngineContext::WebEngineContext()
#ifndef QT_NO_OPENGL
bool tryGL =
- !usingANGLE()
- && (!usingSoftwareDynamicGL()
+ (!usingSoftwareDynamicGL()
// If user requested WebGL support instead of using Skia rendering to
// bitmaps, use software rendering via software OpenGL. This might be less
// performant, but at least provides WebGL support.
@@ -477,10 +500,13 @@ WebEngineContext::WebEngineContext()
if (tryGL) {
if (qt_gl_global_share_context() && qt_gl_global_share_context()->isValid()) {
- // If the native handle is QEGLNativeContext try to use GL ES/2, if there is no native handle
- // assume we are using wayland and try GL ES/2, and finally Ozone demands GL ES/2 too.
+ // If the native handle is QEGLNativeContext try to use GL ES/2.
+ // If there is no native handle, assume we are using wayland and try GL ES/2.
+ // If we are using ANGLE on Windows, use OpenGL ES (2 or 3).
if (qt_gl_global_share_context()->nativeHandle().isNull()
- || !strcmp(qt_gl_global_share_context()->nativeHandle().typeName(), "QEGLNativeContext"))
+ || !strcmp(qt_gl_global_share_context()->nativeHandle().typeName(),
+ "QEGLNativeContext")
+ || usingANGLE())
{
if (qt_gl_global_share_context()->isOpenGLES()) {
glType = gl::kGLImplementationEGLName;
@@ -546,9 +572,16 @@ WebEngineContext::WebEngineContext()
parsedCommandLine->AppendSwitch(switches::kDisableGpu);
}
- content::UtilityProcessHost::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread);
- content::RenderProcessHostImpl::RegisterRendererMainThreadFactory(content::CreateInProcessRendererThread);
- content::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread);
+ bool threadedGpu = true;
+#ifndef QT_NO_OPENGL
+ threadedGpu = QOpenGLContext::supportsThreadedOpenGL();
+#endif
+ registerMainThreadFactories(threadedGpu);
+
+ SetContentClient(new ContentClientQt);
+
+ content::StartBrowserTaskScheduler();
+ content::BrowserTaskExecutor::Create();
mojo::core::Init();
@@ -600,6 +633,10 @@ WebEngineContext::WebEngineContext()
m_printJobManager.reset(new printing::PrintJobManager());
#endif
+#ifndef QT_NO_ACCESSIBILITY
+ m_accessibilityActivationObserver.reset(new AccessibilityActivationObserver());
+#endif
+
content::WebUIControllerFactory::RegisterFactory(WebUIControllerFactoryQt::GetInstance());
}
@@ -609,4 +646,18 @@ printing::PrintJobManager* WebEngineContext::getPrintJobManager()
return m_printJobManager.get();
}
#endif
+
+static QMutex s_spmMutex;
+QAtomicPointer<gpu::SyncPointManager> WebEngineContext::s_syncPointManager;
+
+gpu::SyncPointManager *WebEngineContext::syncPointManager()
+{
+ if (gpu::SyncPointManager *spm = s_syncPointManager.loadAcquire())
+ return spm;
+ QMutexLocker lock(&s_spmMutex);
+ if (!s_syncPointManager)
+ s_syncPointManager.store(new gpu::SyncPointManager());
+ return s_syncPointManager.load();
+}
+
} // namespace
diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h
index 604c85a61..ad02ddf4d 100644
--- a/src/core/web_engine_context.h
+++ b/src/core/web_engine_context.h
@@ -52,6 +52,14 @@ class RunLoop;
namespace content {
class BrowserMainRunner;
class ContentMainRunner;
+class GpuProcess;
+class GpuThreadController;
+class InProcessChildThreadParams;
+}
+
+namespace gpu {
+struct GpuPreferences;
+class SyncPointManager;
}
#if QT_CONFIG(webengine_printing_and_pdf)
@@ -64,9 +72,10 @@ QT_FORWARD_DECLARE_CLASS(QObject)
namespace QtWebEngineCore {
-class ProfileAdapter;
+class AccessibilityActivationObserver;
class ContentMainDelegateQt;
class DevToolsServerQt;
+class ProfileAdapter;
bool usingSoftwareDynamicGL();
@@ -87,12 +96,17 @@ public:
void removeProfileAdapter(ProfileAdapter *profileAdapter);
void destroy();
+ static gpu::SyncPointManager *syncPointManager();
+
private:
friend class base::RefCounted<WebEngineContext>;
friend class ProfileAdapter;
WebEngineContext();
~WebEngineContext();
+ static void registerMainThreadFactories(bool threaded);
+ static void destroyGpuProcess();
+
std::unique_ptr<base::RunLoop> m_runLoop;
std::unique_ptr<ContentMainDelegateQt> m_mainDelegate;
std::unique_ptr<content::ContentMainRunner> m_contentRunner;
@@ -101,12 +115,16 @@ private:
std::unique_ptr<ProfileAdapter> m_defaultProfileAdapter;
std::unique_ptr<DevToolsServerQt> m_devtoolsServer;
QVector<ProfileAdapter*> m_profileAdapters;
+#ifndef QT_NO_ACCESSIBILITY
+ std::unique_ptr<AccessibilityActivationObserver> m_accessibilityActivationObserver;
+#endif
#if QT_CONFIG(webengine_printing_and_pdf)
std::unique_ptr<printing::PrintJobManager> m_printJobManager;
#endif
static scoped_refptr<QtWebEngineCore::WebEngineContext> m_handle;
static bool m_destroyed;
+ static QAtomicPointer<gpu::SyncPointManager> s_syncPointManager;
};
} // namespace
diff --git a/src/core/web_engine_context_threads.cpp b/src/core/web_engine_context_threads.cpp
new file mode 100644
index 000000000..07a86cc69
--- /dev/null
+++ b/src/core/web_engine_context_threads.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "web_engine_context.h"
+
+#include "base/bind.h"
+#include "base/task/post_task.h"
+#include "base/threading/platform_thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "content/browser/gpu/gpu_main_thread_factory.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/utility_process_host.h"
+#include "content/gpu/gpu_child_thread.h"
+#include "content/gpu/gpu_process.h"
+#include "content/gpu/in_process_gpu_thread.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/renderer/in_process_renderer_thread.h"
+#include "content/utility/in_process_utility_thread.h"
+
+#include <memory>
+
+namespace QtWebEngineCore {
+
+struct GpuThreadControllerQt : content::GpuThreadController
+{
+ GpuThreadControllerQt(const content::InProcessChildThreadParams &params, const gpu::GpuPreferences &gpuPreferences)
+ {
+ base::PostTaskWithTraits(
+ FROM_HERE, { content::BrowserThread::UI },
+ base::BindOnce(&GpuThreadControllerQt::createGpuProcess, params, gpuPreferences));
+ }
+ ~GpuThreadControllerQt() override
+ {
+ base::PostTaskWithTraits(
+ FROM_HERE, { content::BrowserThread::UI },
+ base::BindOnce(&GpuThreadControllerQt::destroyGpuProcess));
+ }
+
+ static void createGpuProcess(
+ const content::InProcessChildThreadParams &params,
+ const gpu::GpuPreferences &gpuPreferences)
+ {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (s_gpuProcessDestroyed)
+ return;
+
+ s_gpuProcess = std::make_unique<content::GpuProcess>(base::ThreadPriority::NORMAL);
+ auto gpuInit = std::make_unique<gpu::GpuInit>();
+ gpuInit->InitializeInProcess(base::CommandLine::ForCurrentProcess(), gpuPreferences);
+ auto childThread = new content::GpuChildThread(params, std::move(gpuInit));
+ childThread->Init(base::Time::Now());
+ s_gpuProcess->set_main_thread(childThread);
+ }
+
+ static void destroyGpuProcess()
+ {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (s_gpuProcessDestroyed)
+ return;
+
+ // viz::GpuServiceImpl::~GpuServiceImpl waits for io task.
+ base::ScopedAllowBaseSyncPrimitivesForTesting allow;
+ s_gpuProcess.reset();
+ s_gpuProcessDestroyed = true;
+ }
+
+ static std::unique_ptr<content::GpuProcess> s_gpuProcess;
+ static bool s_gpuProcessDestroyed;
+};
+
+std::unique_ptr<content::GpuProcess> GpuThreadControllerQt::s_gpuProcess;
+bool GpuThreadControllerQt::s_gpuProcessDestroyed = false;
+
+static std::unique_ptr<content::GpuThreadController> createGpuThreadController(
+ const content::InProcessChildThreadParams &params,
+ const gpu::GpuPreferences &gpuPreferences)
+{
+ return std::make_unique<GpuThreadControllerQt>(params, gpuPreferences);
+}
+
+// static
+void WebEngineContext::destroyGpuProcess()
+{
+ GpuThreadControllerQt::destroyGpuProcess();
+}
+
+// static
+void WebEngineContext::registerMainThreadFactories(bool threaded)
+{
+ content::UtilityProcessHost::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread);
+ content::RenderProcessHostImpl::RegisterRendererMainThreadFactory(content::CreateInProcessRendererThread);
+ if (threaded)
+ content::RegisterGpuMainThreadFactory(content::CreateInProcessGpuThread);
+ else
+ content::RegisterGpuMainThreadFactory(createGpuThreadController);
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index 3899ced25..12ffd91e6 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -54,6 +54,7 @@
#include <QDir>
#include <QFileInfo>
#include <QLibraryInfo>
+#include <QLocale>
#include <QStandardPaths>
#include <QString>
diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp
index fc6287dd9..339a3ef0e 100644
--- a/src/core/web_event_factory.cpp
+++ b/src/core/web_event_factory.cpp
@@ -101,7 +101,7 @@ static KeyboardDriver keyboardDriverImpl()
if (platformName == QLatin1Literal("xcb") || platformName == QLatin1Literal("wayland"))
return KeyboardDriver::Xkb;
-#if QT_CONFIG(libinput) && QT_CONFIG(xkbcommon)
+#if QT_CONFIG(libinput)
// Based on QEglFSIntegration::createInputHandlers and QLibInputKeyboard::processKey.
if (platformName == QLatin1Literal("eglfs") && !qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT"))
return KeyboardDriver::Xkb;
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 32fce325b..6698a9736 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,2 +1,2 @@
TEMPLATE = subdirs
-qtHaveModule(designer):qtHaveModule(webenginewidgets): SUBDIRS += qwebengineview
+qtHaveModule(designer): SUBDIRS += qwebengineview
diff --git a/src/src.pro b/src/src.pro
index 218cdb66d..30562686a 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -14,11 +14,7 @@ core.depends = buildtools
SUBDIRS += buildtools \
core \
- process \
- webengine \
- webengine_plugin \
- plugins
-
+ process
qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross_compile {
SUBDIRS += qwebengine_convert_dict
@@ -26,19 +22,11 @@ qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross
qwebengine_convert_dict.depends = core
}
-qtConfig(webengine-testsupport) {
- webengine_testsupport_plugin.subdir = webengine/plugin/testsupport
- webengine_testsupport_plugin.target = sub-webengine-testsupport-plugin
- webengine_testsupport_plugin.depends = webengine
- SUBDIRS += webengine_testsupport_plugin
-}
-
-qtConfig(webengine-ui-delegates) {
- SUBDIRS += webengine/ui \
- webengine/ui2
+qtConfig(webengine-qml) {
+ SUBDIRS += webengine
}
-qtHaveModule(widgets) {
- SUBDIRS += webenginewidgets
+qtConfig(webengine-widgets) {
+ SUBDIRS += plugins webenginewidgets
plugins.depends = webenginewidgets
}
diff --git a/src/webengine/api/qquickwebengineclientcertificateselection.cpp b/src/webengine/api/qquickwebengineclientcertificateselection.cpp
new file mode 100644
index 000000000..56cf1ff64
--- /dev/null
+++ b/src/webengine/api/qquickwebengineclientcertificateselection.cpp
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickwebengineclientcertificateselection_p.h"
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
+
+#include "client_cert_select_controller.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype WebEngineClientCertificateOption
+ \instantiates QQuickWebEngineClientCertificateOption
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.9
+ \brief Represents a client certificate option.
+
+ \sa {WebEngineClientCertificateSelection::certificates} {WebEngineClientCertificateSelection.certificates}
+*/
+
+QQuickWebEngineClientCertificateOption::QQuickWebEngineClientCertificateOption() = default;
+
+QQuickWebEngineClientCertificateOption::QQuickWebEngineClientCertificateOption(QQuickWebEngineClientCertificateSelection *selection, int index)
+ : QObject(), m_selection(selection), m_index(index)
+{}
+
+QQuickWebEngineClientCertificateOption::QQuickWebEngineClientCertificateOption(const QQuickWebEngineClientCertificateOption &other)
+ : QObject(), m_selection(other.m_selection), m_index(other.m_index)
+{}
+
+QQuickWebEngineClientCertificateOption &QQuickWebEngineClientCertificateOption::operator=(const QQuickWebEngineClientCertificateOption &other)
+{
+ m_selection = other.m_selection;
+ m_index = other.m_index;
+ return *this;
+}
+
+/*!
+ \qmlproperty string WebEngineClientCertificateOption::issuer
+ \brief The issuer of the certificate.
+*/
+
+QString QQuickWebEngineClientCertificateOption::issuer() const
+{
+ return m_selection->d_ptr->certificates().at(m_index).issuerDisplayName();
+}
+
+/*!
+ \qmlproperty string WebEngineClientCertificateOption::subject
+ \brief The subject of the certificate.
+*/
+QString QQuickWebEngineClientCertificateOption::subject() const
+{
+ return m_selection->d_ptr->certificates().at(m_index).subjectDisplayName();
+}
+
+/*!
+ \qmlproperty datetime WebEngineClientCertificateOption::effectiveDate
+ \brief The date and time when the certificate becomes valid.
+*/
+QDateTime QQuickWebEngineClientCertificateOption::effectiveDate() const
+{
+ return m_selection->d_ptr->certificates().at(m_index).effectiveDate();
+}
+
+/*!
+ \qmlproperty datetime WebEngineClientCertificateOption::expiryDate
+ \brief The date and time when the certificate becomes invalid.
+*/
+QDateTime QQuickWebEngineClientCertificateOption::expiryDate() const
+{
+ return m_selection->d_ptr->certificates().at(m_index).expiryDate();
+}
+
+/*!
+ \qmlproperty bool WebEngineClientCertificateOption::isSelfSigned
+ \brief Whether the certificate is only self-signed.
+*/
+bool QQuickWebEngineClientCertificateOption::isSelfSigned() const
+{
+ return m_selection->d_ptr->certificates().at(m_index).isSelfSigned();
+}
+
+/*!
+ \qmlmethod void WebEngineClientCertificateOption::select()
+
+ Selects this client certificate option.
+*/
+void QQuickWebEngineClientCertificateOption::select()
+{
+ m_selection->select(m_index);
+}
+
+/*!
+ \qmltype WebEngineClientCertificateSelection
+ \instantiates QQuickWebEngineClientCertificateSelection
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.9
+ \brief Provides a selection of client certificates.
+
+ When a web site requests an SSL client certificate, and one or more certificates
+ are found in the system's client certificate store, this type provides access to
+ the certificates to choose from, as well as a method for selecting one.
+
+ The selection is asynchronous. If no certificate is selected and no copy of the
+ object is kept alive, loading will continue without a certificate.
+
+ \sa {WebEngineView::selectClientCertificate}{WebEngineView.selectClientCertificate}
+*/
+
+QQuickWebEngineClientCertificateSelection::QQuickWebEngineClientCertificateSelection(QSharedPointer<ClientCertSelectController> selectController)
+ : QObject(), d_ptr(selectController)
+{}
+
+int QQuickWebEngineClientCertificateSelection::certificates_count(
+ QQmlListProperty<QQuickWebEngineClientCertificateOption> *p)
+{
+ Q_ASSERT(p && p->object);
+ QQuickWebEngineClientCertificateSelection *d = static_cast<QQuickWebEngineClientCertificateSelection *>(p->object);
+ return d->m_certificates.size();
+}
+
+QQuickWebEngineClientCertificateOption *QQuickWebEngineClientCertificateSelection::certificates_at(
+ QQmlListProperty<QQuickWebEngineClientCertificateOption> *p, int idx)
+{
+ Q_ASSERT(p && p->object);
+ QQuickWebEngineClientCertificateSelection *d = static_cast<QQuickWebEngineClientCertificateSelection *>(p->object);
+ if (idx < 0 || idx >= d->m_certificates.size())
+ return nullptr;
+ return &d->m_certificates[idx];
+}
+
+/*!
+ \qmlproperty list<WebEngineClientCertificateOption> WebEngineClientCertificateSelection::certificates
+ \brief The client certificates available to choose from.
+*/
+
+QQmlListProperty<QQuickWebEngineClientCertificateOption> QQuickWebEngineClientCertificateSelection::certificates()
+{
+ if (m_certificates.empty()) {
+ QVector<QSslCertificate> certificates = d_ptr->certificates();
+ for (int i = 0; i < certificates.count(); ++i)
+ m_certificates.push_back(QQuickWebEngineClientCertificateOption(this, i));
+ }
+
+ return QQmlListProperty<QQuickWebEngineClientCertificateOption>(
+ this, nullptr,
+ certificates_count,
+ certificates_at);
+}
+
+/*!
+ \qmlmethod void WebEngineClientCertificateSelection::select(WebEngineClientCertificateOption certificate)
+
+ Selects the client certificate \a certificate. The certificate must be one
+ of the offered certificates.
+
+ \sa selectNone()
+*/
+void QQuickWebEngineClientCertificateSelection::select(const QQuickWebEngineClientCertificateOption *certificate)
+{
+ select(certificate->m_index);
+}
+
+/*!
+ \qmlmethod void WebEngineClientCertificateSelection::select(int index)
+
+ Selects the client certificate at the index \a index in the list of offered certificates.
+
+ \sa selectNone()
+*/
+void QQuickWebEngineClientCertificateSelection::select(int index)
+{
+ d_ptr->select(index);
+}
+
+/*!
+ \qmlmethod void WebEngineClientCertificateSelection::selectNone()
+
+ Continues without using any of the offered certificates. This is the same
+ action as taken when destroying the last copy of this object if no
+ selection has been made.
+
+ \sa select()
+*/
+void QQuickWebEngineClientCertificateSelection::selectNone()
+{
+ d_ptr->selectNone();
+}
+
+/*!
+ \qmlproperty url WebEngineClientCertificateSelection::host
+ \brief The host and port of the server requesting the client certificate.
+*/
+QUrl QQuickWebEngineClientCertificateSelection::host() const
+{
+ return d_ptr->hostAndPort();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
diff --git a/src/webengine/api/qquickwebengineclientcertificateselection_p.h b/src/webengine/api/qquickwebengineclientcertificateselection_p.h
new file mode 100644
index 000000000..7f5a26296
--- /dev/null
+++ b/src/webengine/api/qquickwebengineclientcertificateselection_p.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWEBENGINECERTSELECTION_P_H
+#define QQUICKWEBENGINECERTSELECTION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtWebEngine/private/qtwebengineglobal_p.h>
+
+#include <QtCore/QDateTime>
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QUrl>
+#include <QtCore/QVector>
+#include <QtQml/QQmlListProperty>
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
+
+QT_BEGIN_NAMESPACE
+
+class ClientCertSelectController;
+class QQuickWebEngineClientCertificateSelection;
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineClientCertificateOption : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(QString issuer READ issuer CONSTANT FINAL)
+ Q_PROPERTY(QString subject READ subject CONSTANT FINAL)
+ Q_PROPERTY(QDateTime effectiveDate READ effectiveDate CONSTANT FINAL)
+ Q_PROPERTY(QDateTime expiryDate READ expiryDate CONSTANT FINAL)
+ Q_PROPERTY(bool isSelfSigned READ isSelfSigned CONSTANT FINAL)
+
+public:
+ QQuickWebEngineClientCertificateOption();
+ QQuickWebEngineClientCertificateOption(const QQuickWebEngineClientCertificateOption &);
+ QQuickWebEngineClientCertificateOption &operator=(const QQuickWebEngineClientCertificateOption &);
+
+ QString issuer() const;
+ QString subject() const;
+ QDateTime effectiveDate() const;
+ QDateTime expiryDate() const;
+ bool isSelfSigned() const;
+
+ Q_INVOKABLE void select();
+
+private:
+ friend class QQuickWebEngineClientCertificateSelection;
+ QQuickWebEngineClientCertificateOption(QQuickWebEngineClientCertificateSelection *selection, int index);
+
+ QQuickWebEngineClientCertificateSelection *m_selection;
+ int m_index;
+};
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineClientCertificateSelection : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(QUrl host READ host CONSTANT FINAL)
+ Q_PROPERTY(QQmlListProperty<QQuickWebEngineClientCertificateOption> certificates READ certificates CONSTANT FINAL)
+
+public:
+ QQuickWebEngineClientCertificateSelection() = default;
+
+ QUrl host() const;
+
+ Q_INVOKABLE void select(int idx);
+ Q_INVOKABLE void select(const QQuickWebEngineClientCertificateOption *certificate);
+ Q_INVOKABLE void selectNone();
+ QQmlListProperty<QQuickWebEngineClientCertificateOption> certificates();
+
+private:
+ friend class QQuickWebEngineViewPrivate;
+ friend class QQuickWebEngineClientCertificateOption;
+
+ static int certificates_count(QQmlListProperty<QQuickWebEngineClientCertificateOption> *p);
+ static QQuickWebEngineClientCertificateOption *certificates_at(QQmlListProperty<QQuickWebEngineClientCertificateOption> *p, int idx);
+
+ explicit QQuickWebEngineClientCertificateSelection(QSharedPointer<ClientCertSelectController>);
+
+ mutable QVector<QQuickWebEngineClientCertificateOption> m_certificates;
+ QSharedPointer<ClientCertSelectController> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QQuickWebEngineClientCertificateOption *)
+Q_DECLARE_METATYPE(QQmlListProperty<QQuickWebEngineClientCertificateOption>)
+Q_DECLARE_METATYPE(QQuickWebEngineClientCertificateSelection *)
+
+#endif
+
+#endif // QQUICKWEBENGINECERTSELECTION_P_H
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index ddc71602b..4448d44d1 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -279,6 +279,12 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info
}
}
+void QQuickWebEngineProfilePrivate::useForGlobalCertificateVerificationChanged()
+{
+ Q_Q(QQuickWebEngineProfile);
+ Q_EMIT q->useForGlobalCertificateVerificationChanged();
+}
+
void QQuickWebEngineProfilePrivate::userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script)
{
Q_ASSERT(p && p->data);
@@ -789,6 +795,102 @@ bool QQuickWebEngineProfile::isSpellCheckEnabled() const
}
/*!
+ \property QQuickWebEngineProfile::useForGlobalCertificateVerification
+ \since 5.13
+
+ This property holds whether this profile is used for downloading and
+ caching during global certificate verification when using the online
+ certificate status protocol (OCSP), certificate revokation lists (CRLs),
+ and authority information access (AIA), for example.
+
+ As long as one profile has this option enabled, all other profiles will be
+ able to use it for certificate verification. Only one profile at a time can
+ have this option enabled. It is recommended that the profile has a disk HTTP
+ cache to avoid needlessly re-downloading.
+
+ By default, no profile has this property enabled.
+
+ Currently, only affects Linux/NSS installations, where having a profile with
+ this role enables OCSP.
+*/
+
+/*!
+ \qmlproperty bool WebEngineProfile::useForGlobalCertificateVerification
+ \since QtWebEngine 1.9
+
+ This property holds whether this profile is used for downloading and
+ caching during global certificate verification when using the online
+ certificate status protocol (OCSP), certificate revokation lists (CRLs),
+ and authority information access (AIA), for example.
+
+ As long as one profile has this option enabled, all other profiles will be
+ able to use it for certificate verification. Only one profile at a time can
+ have this option enabled. It is recommended that the profile has a disk HTTP
+ cache to avoid needlessly re-downloading.
+
+ By default, no profile has this property enabled.
+
+ Currently, only affects Linux/NSS installations, where having a profile with
+ this role enables OCSP.
+*/
+
+void QQuickWebEngineProfile::setUseForGlobalCertificateVerification(bool enable)
+{
+ Q_D(QQuickWebEngineProfile);
+ if (enable != d->profileAdapter()->isUsedForGlobalCertificateVerification()) {
+ d->profileAdapter()->setUseForGlobalCertificateVerification(enable);
+ emit useForGlobalCertificateVerificationChanged();
+ }
+}
+
+bool QQuickWebEngineProfile::isUsedForGlobalCertificateVerification() const
+{
+ const Q_D(QQuickWebEngineProfile);
+ return d->profileAdapter()->isUsedForGlobalCertificateVerification();
+}
+
+/*!
+ \qmlproperty string WebEngineProfile::downloadPath
+ \since QtWebEngine 1.9
+
+ The path to the location where the downloaded files are stored.
+
+ Overrides the default path used for download location.
+
+ If set to the null string, the default path is restored.
+
+ \note By default, the download path is QStandardPaths::DownloadLocation.
+*/
+
+/*!
+ \property QQuickWebEngineProfile::downloadPath
+ \since QtWebEngine 1.9
+
+ The path to the location where the downloaded files are stored.
+
+ Overrides the default path used for download location, setting it to \a path.
+
+ If set to the null string, the default path is restored.
+
+ \note By default, the download path is QStandardPaths::DownloadLocation.
+*/
+
+void QQuickWebEngineProfile::setDownloadPath(const QString &path)
+{
+ Q_D(QQuickWebEngineProfile);
+ if (downloadPath() == path)
+ return;
+ d->profileAdapter()->setDownloadPath(path);
+ emit downloadPathChanged();
+}
+
+QString QQuickWebEngineProfile::downloadPath() const
+{
+ const Q_D(QQuickWebEngineProfile);
+ return d->profileAdapter()->downloadPath();
+}
+
+/*!
Returns the cookie store for this profile.
*/
@@ -840,20 +942,7 @@ void QQuickWebEngineProfile::setRequestInterceptor(QWebEngineUrlRequestIntercept
const QWebEngineUrlSchemeHandler *QQuickWebEngineProfile::urlSchemeHandler(const QByteArray &scheme) const
{
const Q_D(QQuickWebEngineProfile);
- if (d->profileAdapter()->customUrlSchemeHandlers().contains(scheme))
- return d->profileAdapter()->customUrlSchemeHandlers().value(scheme);
- return 0;
-}
-
-static bool checkInternalScheme(const QByteArray &scheme)
-{
- static QSet<QByteArray> internalSchemes;
- if (internalSchemes.isEmpty()) {
- internalSchemes << QByteArrayLiteral("qrc") << QByteArrayLiteral("data") << QByteArrayLiteral("blob")
- << QByteArrayLiteral("http") << QByteArrayLiteral("https") << QByteArrayLiteral("ftp")
- << QByteArrayLiteral("javascript");
- }
- return internalSchemes.contains(scheme);
+ return d->profileAdapter()->urlSchemeHandler(scheme);
}
/*!
@@ -865,25 +954,7 @@ static bool checkInternalScheme(const QByteArray &scheme)
void QQuickWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler)
{
Q_D(QQuickWebEngineProfile);
- Q_ASSERT(handler);
- QByteArray canonicalScheme = scheme.toLower();
- if (checkInternalScheme(canonicalScheme)) {
- qWarning("Cannot install a URL scheme handler overriding internal scheme: %s", scheme.constData());
- return;
- }
-
- if (d->profileAdapter()->customUrlSchemeHandlers().contains(canonicalScheme)) {
- if (d->profileAdapter()->customUrlSchemeHandlers().value(canonicalScheme) != handler)
- qWarning("URL scheme handler already installed for the scheme: %s", scheme.constData());
- return;
- }
-
- if (QWebEngineUrlScheme::schemeByName(canonicalScheme) == QWebEngineUrlScheme())
- qWarning("Please register the custom scheme '%s' via QWebEngineUrlScheme::registerScheme() "
- "before installing the custom scheme handler.", scheme.constData());
-
- d->profileAdapter()->addCustomUrlSchemeHandler(canonicalScheme, handler);
- connect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)));
+ d->profileAdapter()->installUrlSchemeHandler(scheme, handler);
}
/*!
@@ -894,10 +965,7 @@ void QQuickWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, Q
void QQuickWebEngineProfile::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler)
{
Q_D(QQuickWebEngineProfile);
- Q_ASSERT(handler);
- if (!d->profileAdapter()->removeCustomUrlSchemeHandler(handler))
- return;
- disconnect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)));
+ d->profileAdapter()->removeUrlSchemeHandler(handler);
}
/*!
@@ -908,10 +976,7 @@ void QQuickWebEngineProfile::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *
void QQuickWebEngineProfile::removeUrlScheme(const QByteArray &scheme)
{
Q_D(QQuickWebEngineProfile);
- QWebEngineUrlSchemeHandler *handler = d->profileAdapter()->takeCustomUrlSchemeHandler(scheme);
- if (!handler)
- return;
- disconnect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)));
+ d->profileAdapter()->removeUrlScheme(scheme);
}
/*!
@@ -920,12 +985,7 @@ void QQuickWebEngineProfile::removeUrlScheme(const QByteArray &scheme)
void QQuickWebEngineProfile::removeAllUrlSchemeHandlers()
{
Q_D(QQuickWebEngineProfile);
- d->profileAdapter()->clearCustomUrlSchemeHandlers();
-}
-
-void QQuickWebEngineProfile::destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *obj)
-{
- removeUrlSchemeHandler(obj);
+ d->profileAdapter()->removeAllUrlSchemeHandlers();
}
QQuickWebEngineSettings *QQuickWebEngineProfile::settings() const
diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h
index 9fc4f9eca..1e2e3e030 100644
--- a/src/webengine/api/qquickwebengineprofile.h
+++ b/src/webengine/api/qquickwebengineprofile.h
@@ -72,6 +72,12 @@ class Q_WEBENGINE_EXPORT QQuickWebEngineProfile : public QObject {
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)
Q_PROPERTY(QQmlListProperty<QQuickWebEngineScript> userScripts READ userScripts FINAL REVISION 4)
+ Q_PROPERTY(bool useForGlobalCertificateVerification
+ READ isUsedForGlobalCertificateVerification
+ WRITE setUseForGlobalCertificateVerification
+ NOTIFY useForGlobalCertificateVerificationChanged
+ FINAL REVISION 5)
+ Q_PROPERTY(QString downloadPath READ downloadPath WRITE setDownloadPath NOTIFY downloadPathChanged FINAL REVISION 5)
public:
QQuickWebEngineProfile(QObject *parent = Q_NULLPTR);
@@ -137,6 +143,12 @@ public:
QQmlListProperty<QQuickWebEngineScript> userScripts();
+ void setUseForGlobalCertificateVerification(bool b);
+ bool isUsedForGlobalCertificateVerification() const;
+
+ QString downloadPath() const;
+ void setDownloadPath(const QString &path);
+
static QQuickWebEngineProfile *defaultProfile();
Q_SIGNALS:
@@ -151,13 +163,12 @@ Q_SIGNALS:
Q_REVISION(1) void httpAcceptLanguageChanged();
Q_REVISION(3) void spellCheckLanguagesChanged();
Q_REVISION(3) void spellCheckEnabledChanged();
+ Q_REVISION(5) void useForGlobalCertificateVerificationChanged();
+ Q_REVISION(5) void downloadPathChanged();
void downloadRequested(QQuickWebEngineDownloadItem *download);
void downloadFinished(QQuickWebEngineDownloadItem *download);
-private Q_SLOTS:
- void destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *obj);
-
private:
Q_DECLARE_PRIVATE(QQuickWebEngineProfile)
QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *, QObject *parent = Q_NULLPTR);
diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h
index d31ded0ec..d59470f46 100644
--- a/src/webengine/api/qquickwebengineprofile_p.h
+++ b/src/webengine/api/qquickwebengineprofile_p.h
@@ -83,6 +83,8 @@ public:
void downloadRequested(DownloadItemInfo &info) override;
void downloadUpdated(const DownloadItemInfo &info) override;
+ void useForGlobalCertificateVerificationChanged() override;
+
// QQmlListPropertyHelpers
static void userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script);
static int userScripts_count(QQmlListProperty<QQuickWebEngineScript> *p);
diff --git a/src/webengine/api/qquickwebenginetouchhandleprovider.cpp b/src/webengine/api/qquickwebenginetouchhandleprovider.cpp
new file mode 100644
index 000000000..80f4727b6
--- /dev/null
+++ b/src/webengine/api/qquickwebenginetouchhandleprovider.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickwebenginetouchhandleprovider_p_p.h"
+
+// static
+QString QQuickWebEngineTouchHandleProvider::identifier()
+{
+ return QStringLiteral("touchhandle");
+}
+
+// static
+QUrl QQuickWebEngineTouchHandleProvider::url(int orientation)
+{
+ return QUrl(QStringLiteral("image://%1/%2").arg(identifier(), QString::number(orientation)));
+}
+
+QQuickWebEngineTouchHandleProvider::QQuickWebEngineTouchHandleProvider()
+ : QQuickImageProvider(QQuickImageProvider::Image)
+{
+}
+
+QQuickWebEngineTouchHandleProvider::~QQuickWebEngineTouchHandleProvider()
+{
+}
+
+void QQuickWebEngineTouchHandleProvider::init(const QMap<int, QImage> &images)
+{
+ if (!m_touchHandleMap.empty()) {
+ Q_ASSERT(images.size() == m_touchHandleMap.size());
+ return;
+ }
+
+ m_touchHandleMap.unite(images);
+}
+
+QImage QQuickWebEngineTouchHandleProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
+{
+ Q_UNUSED(size);
+ Q_UNUSED(requestedSize);
+
+ Q_ASSERT(m_touchHandleMap.contains(id.toInt()));
+ return m_touchHandleMap.value(id.toInt());
+}
diff --git a/src/webengine/api/qquickwebenginetouchhandleprovider_p_p.h b/src/webengine/api/qquickwebenginetouchhandleprovider_p_p.h
new file mode 100644
index 000000000..277436289
--- /dev/null
+++ b/src/webengine/api/qquickwebenginetouchhandleprovider_p_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWEBENGINETOUCHHANDLEPROVIDER_P_P_H
+#define QQUICKWEBENGINETOUCHHANDLEPROVIDER_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtQuick/QQuickImageProvider>
+#include <QtWebEngine/private/qtwebengineglobal_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineTouchHandleProvider : public QQuickImageProvider {
+public:
+ static QString identifier();
+ static QUrl url(int orientation);
+
+ QQuickWebEngineTouchHandleProvider();
+ ~QQuickWebEngineTouchHandleProvider();
+
+ void init(const QMap<int, QImage> &images);
+ virtual QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
+
+private:
+ QMap<int, QImage> m_touchHandleMap;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QQUICKWEBENGINETOUCHHANDLEPROVIDER_P_P_H
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index b9ae06aeb..59431cadc 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -39,17 +39,18 @@
#include "qquickwebengineview_p.h"
#include "qquickwebengineview_p_p.h"
-#include "qtwebenginecoreglobal_p.h"
#include "authentication_dialog_controller.h"
#include "profile_adapter.h"
#include "certificate_error_controller.h"
#include "file_picker_controller.h"
#include "javascript_dialog_controller.h"
+#include "touch_selection_menu_controller.h"
#include "qquickwebengineaction_p.h"
#include "qquickwebengineaction_p_p.h"
#include "qquickwebenginehistory_p.h"
#include "qquickwebenginecertificateerror_p.h"
+#include "qquickwebengineclientcertificateselection_p.h"
#include "qquickwebenginecontextmenurequest_p.h"
#include "qquickwebenginedialogrequests_p.h"
#include "qquickwebenginefaviconprovider_p_p.h"
@@ -59,6 +60,7 @@
#include "qquickwebengineprofile_p.h"
#include "qquickwebenginesettings_p.h"
#include "qquickwebenginescript_p.h"
+#include "qquickwebenginetouchhandleprovider_p_p.h"
#include "qwebenginequotarequest.h"
#include "qwebengineregisterprotocolhandlerrequest.h"
@@ -300,9 +302,17 @@ void QQuickWebEngineViewPrivate::allowCertificateError(const QSharedPointer<Cert
m_certificateErrorControllers.append(errorController);
}
-void QQuickWebEngineViewPrivate::selectClientCert(const QSharedPointer<ClientCertSelectController> &)
+void QQuickWebEngineViewPrivate::selectClientCert(const QSharedPointer<ClientCertSelectController> &controller)
{
- // Doing nothing will free the select-controller and perform default continue.
+#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineClientCertificateSelection *certSelection = new QQuickWebEngineClientCertificateSelection(controller);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(certSelection);
+ Q_EMIT q->selectClientCertificate(certSelection);
+#else
+ Q_UNUSED(controller);
+#endif
}
void QQuickWebEngineViewPrivate::runGeolocationPermissionRequest(const QUrl &url)
@@ -1130,12 +1140,12 @@ void QQuickWebEngineViewPrivate::didFindText(quint64 requestId, int matchCount)
callback.call(args);
}
-void QQuickWebEngineViewPrivate::didPrintPage(quint64 requestId, const QByteArray &result)
+void QQuickWebEngineViewPrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result)
{
Q_Q(QQuickWebEngineView);
QJSValue callback = m_callbacks.take(requestId);
QJSValueList args;
- args.append(qmlEngine(q)->toScriptValue(result));
+ args.append(qmlEngine(q)->toScriptValue(*(result.data())));
callback.call(args);
}
@@ -1203,6 +1213,39 @@ void QQuickWebEngineViewPrivate::setToolTip(const QString &toolTipText)
ui()->showToolTip(toolTipText);
}
+QtWebEngineCore::TouchHandleDrawableClient *QQuickWebEngineViewPrivate::createTouchHandle(const QMap<int, QImage> &images)
+{
+ return new QQuickWebEngineTouchHandle(ui(), images);
+}
+
+void QQuickWebEngineViewPrivate::showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *menuController, const QRect &selectionBounds, const QSize &handleSize)
+{
+ Q_UNUSED(handleSize);
+
+ const int kSpacingBetweenButtons = 2;
+ const int kMenuButtonMinWidth = 63;
+ const int kMenuButtonMinHeight = 38;
+
+ int buttonCount = menuController->buttonCount();
+ if (buttonCount == 1) {
+ menuController->runContextMenu();
+ return;
+ }
+
+ int width = (kSpacingBetweenButtons * (buttonCount + 1)) + (kMenuButtonMinWidth * buttonCount);
+ int height = kMenuButtonMinHeight + kSpacingBetweenButtons;
+ int x = (selectionBounds.x() + selectionBounds.x() + selectionBounds.width() - width) / 2;
+ int y = selectionBounds.y() - height - 2;
+
+ QRect bounds(x, y, width, height);
+ ui()->showTouchSelectionMenu(menuController, bounds, kSpacingBetweenButtons);
+}
+
+void QQuickWebEngineViewPrivate::hideTouchSelectionMenu()
+{
+ ui()->hideTouchSelectionMenu();
+}
+
bool QQuickWebEngineView::isLoading() const
{
Q_D(const QQuickWebEngineView);
@@ -2277,5 +2320,43 @@ bool QQuickContextMenuBuilder::isMenuItemEnabled(ContextMenuItem menuItem)
Q_UNREACHABLE();
}
+
+QQuickWebEngineTouchHandle::QQuickWebEngineTouchHandle(QtWebEngineCore::UIDelegatesManager *ui, const QMap<int, QImage> &images)
+{
+ Q_ASSERT(ui);
+ m_item.reset(ui->createTouchHandle());
+
+ QQmlEngine *engine = qmlEngine(m_item.data());
+ Q_ASSERT(engine);
+ QQuickWebEngineTouchHandleProvider *touchHandleProvider =
+ static_cast<QQuickWebEngineTouchHandleProvider *>(engine->imageProvider(QQuickWebEngineTouchHandleProvider::identifier()));
+ Q_ASSERT(touchHandleProvider);
+ touchHandleProvider->init(images);
+}
+
+void QQuickWebEngineTouchHandle::setImage(int orientation)
+{
+ QUrl url = QQuickWebEngineTouchHandleProvider::url(orientation);
+ m_item->setProperty("source", url);
+}
+
+void QQuickWebEngineTouchHandle::setBounds(const QRect &bounds)
+{
+ m_item->setProperty("x", bounds.x());
+ m_item->setProperty("y", bounds.y());
+ m_item->setProperty("width", bounds.width());
+ m_item->setProperty("height", bounds.height());
+}
+
+void QQuickWebEngineTouchHandle::setVisible(bool visible)
+{
+ m_item->setProperty("visible", visible);
+}
+
+void QQuickWebEngineTouchHandle::setOpacity(float opacity)
+{
+ m_item->setProperty("opacity", opacity);
+}
+
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h
index ae92b6df0..3a40abf0a 100644
--- a/src/webengine/api/qquickwebengineview_p.h
+++ b/src/webengine/api/qquickwebengineview_p.h
@@ -51,12 +51,11 @@
// We mean it.
//
-#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
#include <QtWebEngine/private/qtwebengineglobal_p.h>
-#include "qquickwebenginescript.h"
#include <QQuickItem>
#include <QtGui/qcolor.h>
+#include "qquickwebenginescript.h"
QT_BEGIN_NAMESPACE
@@ -65,6 +64,7 @@ class QQuickContextMenuBuilder;
class QQuickWebEngineAction;
class QQuickWebEngineAuthenticationDialogRequest;
class QQuickWebEngineCertificateError;
+class QQuickWebEngineClientCertificateSelection;
class QQuickWebEngineColorDialogRequest;
class QQuickWebEngineContextMenuRequest;
class QQuickWebEngineFaviconProvider;
@@ -104,7 +104,7 @@ private:
const bool m_toggleOn;
};
-#define LATEST_WEBENGINEVIEW_REVISION 7
+#define LATEST_WEBENGINEVIEW_REVISION 9
class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem {
Q_OBJECT
@@ -550,6 +550,7 @@ Q_SIGNALS:
Q_REVISION(7) void devToolsViewChanged();
Q_REVISION(7) void registerProtocolHandlerRequested(const QWebEngineRegisterProtocolHandlerRequest &request);
Q_REVISION(8) void printRequested();
+ Q_REVISION(9) void selectClientCertificate(QQuickWebEngineClientCertificateSelection *clientCertSelection);
#if QT_CONFIG(webengine_testsupport)
void testSupportChanged();
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index cbba9b568..3c985cba1 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -53,6 +53,7 @@
#include "qquickwebengineview_p.h"
#include "render_view_context_menu_qt.h"
+#include "touch_handle_drawable_client.h"
#include "web_contents_adapter_client.h"
#include <QPointer>
@@ -64,6 +65,8 @@
namespace QtWebEngineCore {
class RenderWidgetHostViewQtDelegateQuick;
+class TouchHandleDrawableClient;
+class TouchSelectionMenuController;
class UIDelegatesManager;
class WebContentsAdapter;
}
@@ -76,6 +79,7 @@ class QQuickWebEngineContextMenuRequest;
class QQuickWebEngineSettings;
class QQuickWebEngineFaviconProvider;
class QQuickWebEngineProfilePrivate;
+class QQuickWebEngineTouchHandleProvider;
QQuickWebEngineView::WebAction editorActionForKeyEvent(QKeyEvent* event);
@@ -128,7 +132,7 @@ public:
void didFetchDocumentMarkup(quint64, const QString&) override { }
void didFetchDocumentInnerText(quint64, const QString&) override { }
void didFindText(quint64, int) override;
- void didPrintPage(quint64 requestId, const QByteArray &result) override;
+ void didPrintPage(quint64 requestId, QSharedPointer<QByteArray>) override;
void didPrintPageToPdf(const QString &filePath, bool success) override;
void passOnFocus(bool reverse) override;
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override;
@@ -152,6 +156,9 @@ public:
bool supportsDragging() const override;
bool isEnabled() const override;
void setToolTip(const QString &toolTipText) override;
+ QtWebEngineCore::TouchHandleDrawableClient *createTouchHandle(const QMap<int, QImage> &images) override;
+ void showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *, const QRect &, const QSize &) override;
+ void hideTouchSelectionMenu() override;
const QObject *holdingQObject() const override;
ClientType clientType() override { return QtWebEngineCore::WebContentsAdapterClient::QmlClient; }
@@ -253,6 +260,19 @@ private:
QObject *m_menu;
};
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineTouchHandle : public QtWebEngineCore::TouchHandleDrawableClient {
+public:
+ QQuickWebEngineTouchHandle(QtWebEngineCore::UIDelegatesManager *ui, const QMap<int, QImage> &images);
+
+ void setImage(int orientation) override;
+ void setBounds(const QRect &bounds) override;
+ void setVisible(bool visible) override;
+ void setOpacity(float opacity) override;
+
+private:
+ QScopedPointer<QQuickItem> m_item;
+};
+
QT_END_NAMESPACE
#endif // QQUICKWEBENGINEVIEW_P_P_H
diff --git a/src/webengine/api/qtwebengineglobal.h b/src/webengine/api/qtwebengineglobal.h
index 2d83be674..c2b33778a 100644
--- a/src/webengine/api/qtwebengineglobal.h
+++ b/src/webengine/api/qtwebengineglobal.h
@@ -41,6 +41,7 @@
#define QTWEBENGINEGLOBAL_H
#include <QtCore/qglobal.h>
+#include <QtWebEngine/qtwebengine-config.h>
QT_BEGIN_NAMESPACE
diff --git a/src/webengine/api/qtwebengineglobal_p.h b/src/webengine/api/qtwebengineglobal_p.h
index 7058bef09..2d30f75b0 100644
--- a/src/webengine/api/qtwebengineglobal_p.h
+++ b/src/webengine/api/qtwebengineglobal_p.h
@@ -51,7 +51,9 @@
// We mean it.
//
-#include "qtwebengineglobal.h"
+#include <QtWebEngine/qtwebengineglobal.h>
+#include <QtCore/private/qglobal_p.h>
+#include <QtWebEngine/private/qtwebengine-config_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/webengine/configure.json b/src/webengine/configure.json
new file mode 100644
index 000000000..ec5ad34d9
--- /dev/null
+++ b/src/webengine/configure.json
@@ -0,0 +1,29 @@
+{
+ "module": "webengine",
+ "depends": [
+ "webenginecore-private"
+ ],
+ "features": {
+ "webengine-ui-delegates": {
+ "label": "UI Delegates",
+ "section": "WebEngine",
+ "output": [ "privateFeature" ]
+ },
+ "webengine-testsupport": {
+ "label": "Test Support",
+ "autoDetect": "features.private_tests || call.isTestsInBuildParts",
+ "output": [ "privateFeature" ]
+ }
+ },
+ "summary": [
+ {
+ "section": "Qt WebEngineQml",
+ "condition": "features.webengine-qml",
+ "entries": [
+ "webengine-ui-delegates",
+ "webengine-testsupport"
+ ]
+ }
+ ]
+}
+
diff --git a/src/webengine/doc/src/webengineview_lgpl.qdoc b/src/webengine/doc/src/webengineview_lgpl.qdoc
index 0e25e16f3..d96aabc97 100644
--- a/src/webengine/doc/src/webengineview_lgpl.qdoc
+++ b/src/webengine/doc/src/webengineview_lgpl.qdoc
@@ -1475,3 +1475,19 @@
\sa printToPdf
*/
+
+/*!
+ \qmlsignal WebEngineView::selectClientCertificate(WebEngineClientCertificateSelection clientCertificateSelection)
+ \since QtWebEngine 1.9
+
+ This signal is emitted when a web site requests an SSL client certificate, and one or more were
+ found in the system's client certificate store.
+
+ Handling the signal is asynchronous, and loading will be waiting until a certificate is selected,
+ or the last copy of \a clientCertificateSelection is destroyed.
+
+ If the signal is not handled, \a clientCertificateSelection is automatically destroyed, and loading
+ will continue without a client certificate.
+
+ \sa WebEngineClientCertificateSelection
+*/
diff --git a/src/webengine/module.pro b/src/webengine/module.pro
new file mode 100644
index 000000000..49a1086b2
--- /dev/null
+++ b/src/webengine/module.pro
@@ -0,0 +1,94 @@
+include($$QTWEBENGINE_OUT_ROOT/src/webengine/qtwebengine-config.pri)
+QT_FOR_CONFIG += webengine-private
+
+TARGET = QtWebEngine
+MODULE = webengine
+
+# For our export macros
+DEFINES += QT_BUILD_WEBENGINE_LIB
+
+QT += qml quick webenginecore
+QT_PRIVATE += quick-private gui-private core-private webenginecore-private
+
+QMAKE_DOCS = $$PWD/doc/qtwebengine.qdocconf
+
+INCLUDEPATH += $$PWD api ../core ../core/api
+
+SOURCES = \
+ api/qquickwebengineaction.cpp \
+ api/qquickwebenginecertificateerror.cpp \
+ api/qquickwebengineclientcertificateselection.cpp \
+ api/qquickwebenginecontextmenurequest.cpp \
+ api/qquickwebenginedialogrequests.cpp \
+ api/qquickwebenginedownloaditem.cpp \
+ api/qquickwebenginehistory.cpp \
+ api/qquickwebenginefaviconprovider.cpp \
+ api/qquickwebengineloadrequest.cpp \
+ api/qquickwebenginenavigationrequest.cpp \
+ api/qquickwebenginenewviewrequest.cpp \
+ api/qquickwebengineprofile.cpp \
+ api/qquickwebenginescript.cpp \
+ api/qquickwebenginesettings.cpp \
+ api/qquickwebenginesingleton.cpp \
+ api/qquickwebenginetouchhandleprovider.cpp \
+ api/qquickwebengineview.cpp \
+ api/qtwebengineglobal.cpp \
+ render_widget_host_view_qt_delegate_quick.cpp \
+ render_widget_host_view_qt_delegate_quickwindow.cpp \
+ ui_delegates_manager.cpp
+
+HEADERS = \
+ api/qtwebengineglobal.h \
+ api/qtwebengineglobal_p.h \
+ api/qquickwebengineaction_p.h \
+ api/qquickwebengineaction_p_p.h \
+ api/qquickwebenginecertificateerror_p.h \
+ api/qquickwebengineclientcertificateselection_p.h \
+ api/qquickwebenginecontextmenurequest_p.h \
+ api/qquickwebenginedialogrequests_p.h \
+ api/qquickwebenginedownloaditem_p.h \
+ api/qquickwebenginedownloaditem_p_p.h \
+ api/qquickwebenginehistory_p.h \
+ api/qquickwebenginefaviconprovider_p_p.h \
+ api/qquickwebengineloadrequest_p.h \
+ api/qquickwebenginenavigationrequest_p.h \
+ api/qquickwebenginenewviewrequest_p.h \
+ api/qquickwebengineprofile.h \
+ api/qquickwebengineprofile_p.h \
+ api/qquickwebenginescript.h \
+ api/qquickwebenginescript_p.h \
+ api/qquickwebenginesettings_p.h \
+ api/qquickwebenginesingleton_p.h \
+ api/qquickwebenginetouchhandleprovider_p_p.h \
+ api/qquickwebengineview_p.h \
+ api/qquickwebengineview_p_p.h \
+ render_widget_host_view_qt_delegate_quick.h \
+ render_widget_host_view_qt_delegate_quickwindow.h \
+ ui_delegates_manager.h
+
+qtConfig(webengine-testsupport) {
+ QT_PRIVATE += testlib
+ SOURCES += api/qquickwebenginetestsupport.cpp
+ HEADERS += api/qquickwebenginetestsupport_p.h
+}
+
+!build_pass {
+ python = $$pythonPathForShell()
+ chromium_attributions.commands = \
+ cd $$shell_quote($$shell_path($$PWD/../3rdparty)) && \
+ $$python chromium/tools/licenses.py \
+ --file-template ../../tools/about_credits.tmpl \
+ --entry-template ../../tools/about_credits_entry.tmpl credits \
+ $$shell_quote($$shell_path($$OUT_PWD/chromium_attributions.qdoc))
+ chromium_attributions.CONFIG += phony
+
+ QMAKE_EXTRA_TARGETS += chromium_attributions
+
+ prepare_docs {
+ prepare_docs.depends += chromium_attributions
+ } else {
+ html_docs.depends += chromium_attributions
+ }
+}
+
+load(qt_module)
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index 84a12c930..0e63989ee 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -40,22 +40,23 @@
#include <QtQml/qqmlextensionplugin.h>
#include <QtWebEngine/QQuickWebEngineProfile>
-#include "qquickwebenginecertificateerror_p.h"
-#include "qquickwebenginecontextmenurequest_p.h"
-#include "qquickwebenginedialogrequests_p.h"
-#include "qquickwebenginedownloaditem_p.h"
-#include "qquickwebenginehistory_p.h"
-#include "qquickwebenginefaviconprovider_p_p.h"
-#include "qquickwebengineloadrequest_p.h"
-#include "qquickwebenginenavigationrequest_p.h"
-#include "qquickwebenginenewviewrequest_p.h"
-#include "qquickwebenginesettings_p.h"
-#include "qquickwebenginesingleton_p.h"
-#include "qquickwebengineview_p.h"
-#include "qquickwebengineaction_p.h"
-#include "qwebenginequotarequest.h"
-#include "qwebengineregisterprotocolhandlerrequest.h"
-#include "qtwebengineversion.h"
+#include <QtWebEngine/private/qquickwebenginecertificateerror_p.h>
+#include <QtWebEngine/private/qquickwebengineclientcertificateselection_p.h>
+#include <QtWebEngine/private/qquickwebenginecontextmenurequest_p.h>
+#include <QtWebEngine/private/qquickwebenginedialogrequests_p.h>
+#include <QtWebEngine/private/qquickwebenginedownloaditem_p.h>
+#include <QtWebEngine/private/qquickwebenginehistory_p.h>
+#include <QtWebEngine/private/qquickwebenginefaviconprovider_p_p.h>
+#include <QtWebEngine/private/qquickwebengineloadrequest_p.h>
+#include <QtWebEngine/private/qquickwebenginenavigationrequest_p.h>
+#include <QtWebEngine/private/qquickwebenginenewviewrequest_p.h>
+#include <QtWebEngine/private/qquickwebenginesettings_p.h>
+#include <QtWebEngine/private/qquickwebenginesingleton_p.h>
+#include <QtWebEngine/private/qquickwebenginetouchhandleprovider_p_p.h>
+#include <QtWebEngine/private/qquickwebengineview_p.h>
+#include <QtWebEngine/private/qquickwebengineaction_p.h>
+#include <QtWebEngineCore/qwebenginequotarequest.h>
+#include <QtWebEngineCore/qwebengineregisterprotocolhandlerrequest.h>
QT_BEGIN_NAMESPACE
@@ -73,6 +74,7 @@ public:
{
Q_UNUSED(uri);
engine->addImageProvider(QQuickWebEngineFaviconProvider::identifier(), new QQuickWebEngineFaviconProvider);
+ engine->addImageProvider(QQuickWebEngineTouchHandleProvider::identifier(), new QQuickWebEngineTouchHandleProvider);
}
void registerTypes(const char *uri) override
@@ -91,11 +93,13 @@ public:
qmlRegisterType<QQuickWebEngineView, 6>(uri, 1, 6, "WebEngineView");
qmlRegisterType<QQuickWebEngineView, 7>(uri, 1, 7, "WebEngineView");
qmlRegisterType<QQuickWebEngineView, 8>(uri, 1, 8, "WebEngineView");
+ qmlRegisterType<QQuickWebEngineView, 9>(uri, 1, 9, "WebEngineView");
qmlRegisterType<QQuickWebEngineProfile>(uri, 1, 1, "WebEngineProfile");
qmlRegisterType<QQuickWebEngineProfile, 1>(uri, 1, 2, "WebEngineProfile");
qmlRegisterType<QQuickWebEngineProfile, 2>(uri, 1, 3, "WebEngineProfile");
qmlRegisterType<QQuickWebEngineProfile, 3>(uri, 1, 4, "WebEngineProfile");
qmlRegisterType<QQuickWebEngineProfile, 4>(uri, 1, 5, "WebEngineProfile");
+ qmlRegisterType<QQuickWebEngineProfile, 5>(uri, 1, 9, "WebEngineProfile");
qmlRegisterType<QQuickWebEngineScript>(uri, 1, 1, "WebEngineScript");
qmlRegisterUncreatableType<QQuickWebEngineCertificateError>(uri, 1, 1, "WebEngineCertificateError", msgUncreatableType("WebEngineCertificateError"));
qmlRegisterUncreatableType<QQuickWebEngineDownloadItem>(uri, 1, 1, "WebEngineDownloadItem",
@@ -153,6 +157,11 @@ public:
qmlRegisterUncreatableType<QWebEngineRegisterProtocolHandlerRequest>(uri, 1, 7, "RegisterProtocolHandlerRequest",
msgUncreatableType("RegisterProtocolHandlerRequest"));
qmlRegisterUncreatableType<QQuickWebEngineAction>(uri, 1, 8, "WebEngineAction", msgUncreatableType("WebEngineAction"));
+ qmlRegisterUncreatableType<QQuickWebEngineClientCertificateSelection>(uri, 1, 9, "WebEngineClientCertificateSelection",
+ tr("Cannot create a separate instance of WebEngineClientCertificateSelection"));
+ qmlRegisterUncreatableType<QQuickWebEngineClientCertificateOption>(uri, 1, 9, "WebEngineClientCertificateOption",
+ tr("Cannot create a separate instance of WebEngineClientCertificateOption"));
+
}
private:
diff --git a/src/webengine/plugin/plugin.pro b/src/webengine/plugin/plugin.pro
index b6652fa26..102f9a9fe 100644
--- a/src/webengine/plugin/plugin.pro
+++ b/src/webengine/plugin/plugin.pro
@@ -1,13 +1,11 @@
CXX_MODULE = qml
TARGET = qtwebengineplugin
TARGETPATH = QtWebEngine
-IMPORT_VERSION = 1.8
+IMPORT_VERSION = 1.9
-QT += webengine qml quick
+QT += qml quick
QT_PRIVATE += core-private webenginecore-private webengine-private
-INCLUDEPATH += $$QTWEBENGINE_ROOT/src/core $$QTWEBENGINE_ROOT/src/core/api $$QTWEBENGINE_ROOT/src/webengine $$QTWEBENGINE_ROOT/src/webengine/api $$QTWEBENGINE_ROOT/include/QtWebEngine
-
SOURCES = plugin.cpp
load(qml_plugin)
diff --git a/src/webengine/plugin/plugins.qmltypes b/src/webengine/plugin/plugins.qmltypes
index 1f295ac57..435124e30 100644
--- a/src/webengine/plugin/plugins.qmltypes
+++ b/src/webengine/plugin/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.8'
+// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.9'
Module {
dependencies: ["QtQuick 2.8"]
@@ -437,9 +437,10 @@ Module {
"QtWebEngine/WebEngineProfile 1.2",
"QtWebEngine/WebEngineProfile 1.3",
"QtWebEngine/WebEngineProfile 1.4",
- "QtWebEngine/WebEngineProfile 1.5"
+ "QtWebEngine/WebEngineProfile 1.5",
+ "QtWebEngine/WebEngineProfile 1.9"
]
- exportMetaObjectRevisions: [0, 1, 2, 3, 4]
+ exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5]
Enum {
name: "HttpCacheType"
values: {
@@ -474,9 +475,13 @@ Module {
isList: true
isReadonly: true
}
+ Property { name: "useForGlobalCertificateVerification"; revision: 5; type: "bool" }
+ Property { name: "downloadPath"; revision: 5; type: "string" }
Signal { name: "httpAcceptLanguageChanged"; revision: 1 }
Signal { name: "spellCheckLanguagesChanged"; revision: 3 }
Signal { name: "spellCheckEnabledChanged"; revision: 3 }
+ Signal { name: "useForGlobalCertificateVerificationChanged"; revision: 5 }
+ Signal { name: "downloadPathChanged"; revision: 5 }
Signal {
name: "downloadRequested"
Parameter { name: "download"; type: "QQuickWebEngineDownloadItem"; isPointer: true }
@@ -664,9 +669,10 @@ Module {
"QtWebEngine/WebEngineView 1.5",
"QtWebEngine/WebEngineView 1.6",
"QtWebEngine/WebEngineView 1.7",
- "QtWebEngine/WebEngineView 1.8"
+ "QtWebEngine/WebEngineView 1.8",
+ "QtWebEngine/WebEngineView 1.9"
]
- exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6, 7, 8]
+ exportMetaObjectRevisions: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Enum {
name: "NavigationRequestAction"
values: {
diff --git a/src/webengine/plugin/testsupport/plugin.cpp b/src/webengine/testsupport/plugin.cpp
index d5c43a859..7a1e73d8b 100644
--- a/src/webengine/plugin/testsupport/plugin.cpp
+++ b/src/webengine/testsupport/plugin.cpp
@@ -39,7 +39,7 @@
#include <QtQml>
-#include "qquickwebenginetestsupport_p.h"
+#include <QtWebEngine/private/qquickwebenginetestsupport_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/webengine/plugin/testsupport/qmldir b/src/webengine/testsupport/qmldir
index 7fff80251..7fff80251 100644
--- a/src/webengine/plugin/testsupport/qmldir
+++ b/src/webengine/testsupport/qmldir
diff --git a/src/webengine/plugin/testsupport/testsupport.pro b/src/webengine/testsupport/testsupport.pro
index 2804635f8..a24796675 100644
--- a/src/webengine/plugin/testsupport/testsupport.pro
+++ b/src/webengine/testsupport/testsupport.pro
@@ -3,11 +3,9 @@ TARGET = qtwebenginetestsupportplugin
TARGETPATH = QtWebEngine/testsupport
IMPORT_VERSION = 1.0
-QT += webengine qml quick
+QT += qml quick
QT_PRIVATE += webengine-private gui-private
-INCLUDEPATH += $$QTWEBENGINE_ROOT/src/core $$QTWEBENGINE_ROOT/src/webengine $$QTWEBENGINE_ROOT/src/webengine/api
-
SOURCES = plugin.cpp
load(qml_plugin)
diff --git a/src/webengine/ui/TouchHandle.qml b/src/webengine/ui/TouchHandle.qml
new file mode 100644
index 000000000..76a93829e
--- /dev/null
+++ b/src/webengine/ui/TouchHandle.qml
@@ -0,0 +1,42 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+
+Image { }
diff --git a/src/webengine/ui/TouchSelectionMenu.qml b/src/webengine/ui/TouchSelectionMenu.qml
new file mode 100644
index 000000000..7cf16b554
--- /dev/null
+++ b/src/webengine/ui/TouchSelectionMenu.qml
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Layouts 1.3
+
+Rectangle {
+ id: menu
+
+ signal cutTriggered
+ signal copyTriggered
+ signal pasteTriggered
+ signal contextMenuTriggered
+
+ property bool isCutEnabled: false
+ property bool isCopyEnabled: false
+ property bool isPasteEnabled: false
+
+ property color borderColor: "darkGray"
+ property color bgColor: "white"
+
+ radius: 4
+ border.color: borderColor
+ color: borderColor
+ antialiasing: true
+
+ RowLayout {
+ anchors.fill: parent
+ spacing: parent.border.width
+ anchors.margins: parent.border.width
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ radius: menu.radius
+ color: bgColor
+ visible: isCutEnabled
+
+ Text {
+ id: cutText
+ anchors.centerIn: parent
+ text: "Cut"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ parent.color = borderColor;
+ cutText.color = "white";
+ }
+ onReleased: {
+ parent.color = bgColor;
+ cutText.color = "black";
+ cutTriggered();
+ }
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ radius: menu.radius
+ color: bgColor
+ visible: isCopyEnabled
+
+ Text {
+ id: copyText
+ anchors.centerIn: parent
+ text: "Copy"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ parent.color = borderColor;
+ copyText.color = "white";
+ }
+ onReleased: {
+ parent.color = bgColor;
+ copyText.color = "black";
+ copyTriggered();
+ }
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ radius: menu.radius
+ color: bgColor
+ visible: isPasteEnabled
+
+ Text {
+ id: pasteText
+ anchors.centerIn: parent
+ text: "Paste"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ parent.color = borderColor;
+ pasteText.color = "white";
+ }
+ onReleased: {
+ parent.color = bgColor;
+ pasteText.color = "black";
+ pasteTriggered();
+ }
+ }
+ }
+
+ Rectangle {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+ radius: menu.radius
+ color: bgColor
+
+ Text {
+ id: contextMenuText
+ anchors.centerIn: parent
+ text: "..."
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ parent.color = borderColor;
+ contextMenuText.color = "white";
+ }
+ onReleased: {
+ parent.color = bgColor;
+ contextMenuText.color = "black";
+ contextMenuTriggered();
+ }
+ }
+ }
+ }
+}
diff --git a/src/webengine/ui/ui.pro b/src/webengine/ui/ui.pro
index eb6bf435c..69f754e0c 100644
--- a/src/webengine/ui/ui.pro
+++ b/src/webengine/ui/ui.pro
@@ -13,6 +13,8 @@ QML_FILES += \
Menu.qml \
MenuItem.qml \
MenuSeparator.qml \
- ToolTip.qml
+ ToolTip.qml \
+ TouchHandle.qml \
+ TouchSelectionMenu.qml
load(qml_module)
diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp
index 7e49bc77d..da120ab69 100644
--- a/src/webengine/ui_delegates_manager.cpp
+++ b/src/webengine/ui_delegates_manager.cpp
@@ -44,6 +44,7 @@
#include <color_chooser_controller.h>
#include <file_picker_controller.h>
#include <javascript_dialog_controller.h>
+#include <touch_selection_menu_controller.h>
#include <web_contents_adapter_client.h>
#include <QFileInfo>
@@ -54,6 +55,7 @@
#include <QCursor>
#include <QList>
#include <QScreen>
+#include <QTimer>
#include <QGuiApplication>
// Uncomment for QML debugging
@@ -125,6 +127,7 @@ const char *defaultPropertyName(QObject *obj)
UIDelegatesManager::UIDelegatesManager(QQuickWebEngineView *view)
: m_view(view)
, m_toolTip(nullptr)
+ , m_touchSelectionMenu(nullptr)
FOR_EACH_COMPONENT_TYPE(COMPONENT_MEMBER_INIT, NO_SEPARATOR)
{
}
@@ -568,6 +571,82 @@ void UIDelegatesManager::showToolTip(const QString &text)
QMetaObject::invokeMethod(m_toolTip.data(), "open");
}
+QQuickItem *UIDelegatesManager::createTouchHandle()
+{
+ if (!ensureComponentLoaded(TouchHandle))
+ return nullptr;
+
+ QQmlContext *context = qmlContext(m_view);
+ QObject *touchHandle = touchHandleComponent->beginCreate(context);
+ QQuickItem *item = qobject_cast<QQuickItem *>(touchHandle);
+ Q_ASSERT(item);
+ item->setParentItem(m_view);
+ touchHandleComponent->completeCreate();
+
+ return item;
+}
+
+void UIDelegatesManager::showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *menuController, const QRect &bounds, const int spacing)
+{
+ if (!ensureComponentLoaded(TouchSelectionMenu))
+ return;
+
+ QQmlContext *context = qmlContext(m_view);
+ m_touchSelectionMenu.reset(touchSelectionMenuComponent->beginCreate(context));
+ if (QQuickItem *item = qobject_cast<QQuickItem *>(m_touchSelectionMenu.data()))
+ item->setParentItem(m_view);
+ m_touchSelectionMenu->setParent(m_view);
+
+ QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("width")).write(bounds.width());
+ QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("height")).write(bounds.height());
+ QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("x")).write(bounds.x());
+ QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("y")).write(bounds.y());
+ QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("border.width")).write(spacing);
+
+ // Cut button
+ bool cutEnabled = menuController->isCommandEnabled(TouchSelectionMenuController::Cut);
+ QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("isCutEnabled")).write(cutEnabled);
+ if (cutEnabled) {
+ QQmlProperty cutSignal(m_touchSelectionMenu.data(), QStringLiteral("onCutTriggered"));
+ CHECK_QML_SIGNAL_PROPERTY(cutSignal, touchSelectionMenuComponent->url());
+ int cutIndex = menuController->metaObject()->indexOfSlot("cut()");
+ QObject::connect(m_touchSelectionMenu.data(), cutSignal.method(), menuController, menuController->metaObject()->method(cutIndex));
+ }
+
+ // Copy button
+ bool copyEnabled = menuController->isCommandEnabled(TouchSelectionMenuController::Copy);
+ QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("isCopyEnabled")).write(copyEnabled);
+ if (copyEnabled) {
+ QQmlProperty copySignal(m_touchSelectionMenu.data(), QStringLiteral("onCopyTriggered"));
+ CHECK_QML_SIGNAL_PROPERTY(copySignal, touchSelectionMenuComponent->url());
+ int copyIndex = menuController->metaObject()->indexOfSlot("copy()");
+ QObject::connect(m_touchSelectionMenu.data(), copySignal.method(), menuController, menuController->metaObject()->method(copyIndex));
+ }
+
+ // Paste button
+ bool pasteEnabled = menuController->isCommandEnabled(TouchSelectionMenuController::Paste);
+ QQmlProperty(m_touchSelectionMenu.data(), QStringLiteral("isPasteEnabled")).write(pasteEnabled);
+ if (pasteEnabled) {
+ QQmlProperty pasteSignal(m_touchSelectionMenu.data(), QStringLiteral("onPasteTriggered"));
+ CHECK_QML_SIGNAL_PROPERTY(pasteSignal, touchSelectionMenuComponent->url());
+ int pasteIndex = menuController->metaObject()->indexOfSlot("paste()");
+ QObject::connect(m_touchSelectionMenu.data(), pasteSignal.method(), menuController, menuController->metaObject()->method(pasteIndex));
+ }
+
+ // Context menu button
+ QQmlProperty contextMenuSignal(m_touchSelectionMenu.data(), QStringLiteral("onContextMenuTriggered"));
+ CHECK_QML_SIGNAL_PROPERTY(contextMenuSignal, touchSelectionMenuComponent->url());
+ int contextMenuIndex = menuController->metaObject()->indexOfSlot("runContextMenu()");
+ QObject::connect(m_touchSelectionMenu.data(), contextMenuSignal.method(), menuController, menuController->metaObject()->method(contextMenuIndex));
+
+ touchSelectionMenuComponent->completeCreate();
+}
+
+void UIDelegatesManager::hideTouchSelectionMenu()
+{
+ QTimer::singleShot(0, m_view, [this] { m_touchSelectionMenu.reset(); });
+}
+
UI2DelegatesManager::UI2DelegatesManager(QQuickWebEngineView *view) : UIDelegatesManager(view)
{
diff --git a/src/webengine/ui_delegates_manager.h b/src/webengine/ui_delegates_manager.h
index 18457e4ed..4b6e291b2 100644
--- a/src/webengine/ui_delegates_manager.h
+++ b/src/webengine/ui_delegates_manager.h
@@ -61,6 +61,8 @@
F(FilePicker, filePicker) SEPARATOR \
F(AuthenticationDialog, authenticationDialog) SEPARATOR \
F(ToolTip, toolTip) SEPARATOR \
+ F(TouchHandle, touchHandle) SEPARATOR \
+ F(TouchSelectionMenu, touchSelectionMenu) SEPARATOR \
#define COMMA_SEPARATOR ,
#define SEMICOLON_SEPARATOR ;
@@ -81,6 +83,7 @@ namespace QtWebEngineCore {
class AuthenticationDialogController;
class JavaScriptDialogController;
class FilePickerController;
+class TouchSelectionMenuController;
const char *defaultPropertyName(QObject *obj);
@@ -110,6 +113,9 @@ public:
void showFilePicker(QSharedPointer<FilePickerController>);
virtual void showMenu(QObject *menu);
void showToolTip(const QString &text);
+ QQuickItem *createTouchHandle();
+ void showTouchSelectionMenu(TouchSelectionMenuController *, const QRect &, const int spacing);
+ void hideTouchSelectionMenu();
protected:
bool ensureComponentLoaded(ComponentType);
@@ -117,6 +123,7 @@ protected:
QQuickWebEngineView *m_view;
QScopedPointer<QObject> m_toolTip;
QStringList m_importDirs;
+ QScopedPointer<QObject> m_touchSelectionMenu;
FOR_EACH_COMPONENT_TYPE(MEMBER_DECLARATION, SEMICOLON_SEPARATOR)
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index 418ade9a8..23668229e 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -1,89 +1,19 @@
-include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) # workaround for QTBUG-68093
-QT_FOR_CONFIG += webenginecore-private
+TEMPLATE = subdirs
-TARGET = QtWebEngine
+qml_module.file = module.pro
+qml_plugin.file = plugin/plugin.pro
-# For our export macros
-DEFINES += QT_BUILD_WEBENGINE_LIB
+qml_plugin.depends = qml_module
-QT += qml quick webenginecore
-QT_PRIVATE += quick-private gui-private core-private webenginecore-private
-
-QMAKE_DOCS = $$PWD/doc/qtwebengine.qdocconf
-
-INCLUDEPATH += $$PWD api ../core ../core/api
-
-SOURCES = \
- api/qquickwebengineaction.cpp \
- api/qquickwebenginecertificateerror.cpp \
- api/qquickwebenginecontextmenurequest.cpp \
- api/qquickwebenginedialogrequests.cpp \
- api/qquickwebenginedownloaditem.cpp \
- api/qquickwebenginehistory.cpp \
- api/qquickwebenginefaviconprovider.cpp \
- api/qquickwebengineloadrequest.cpp \
- api/qquickwebenginenavigationrequest.cpp \
- api/qquickwebenginenewviewrequest.cpp \
- api/qquickwebengineprofile.cpp \
- api/qquickwebenginescript.cpp \
- api/qquickwebenginesettings.cpp \
- api/qquickwebenginesingleton.cpp \
- api/qquickwebengineview.cpp \
- api/qtwebengineglobal.cpp \
- render_widget_host_view_qt_delegate_quick.cpp \
- render_widget_host_view_qt_delegate_quickwindow.cpp \
- ui_delegates_manager.cpp
-
-HEADERS = \
- api/qtwebengineglobal.h \
- api/qtwebengineglobal_p.h \
- api/qquickwebengineaction_p.h \
- api/qquickwebengineaction_p_p.h \
- api/qquickwebenginecertificateerror_p.h \
- api/qquickwebenginecontextmenurequest_p.h \
- api/qquickwebenginedialogrequests_p.h \
- api/qquickwebenginedownloaditem_p.h \
- api/qquickwebenginedownloaditem_p_p.h \
- api/qquickwebenginehistory_p.h \
- api/qquickwebenginefaviconprovider_p_p.h \
- api/qquickwebengineloadrequest_p.h \
- api/qquickwebenginenavigationrequest_p.h \
- api/qquickwebenginenewviewrequest_p.h \
- api/qquickwebengineprofile.h \
- api/qquickwebengineprofile_p.h \
- api/qquickwebenginescript.h \
- api/qquickwebenginescript_p.h \
- api/qquickwebenginesettings_p.h \
- api/qquickwebenginesingleton_p.h \
- api/qquickwebengineview_p.h \
- api/qquickwebengineview_p_p.h \
- render_widget_host_view_qt_delegate_quick.h \
- render_widget_host_view_qt_delegate_quickwindow.h \
- ui_delegates_manager.h
+SUBDIRS += qml_module qml_plugin
qtConfig(webengine-testsupport) {
- QT_PRIVATE += testlib
- SOURCES += api/qquickwebenginetestsupport.cpp
- HEADERS += api/qquickwebenginetestsupport_p.h
+ testsupport_plugin.file = testsupport/testsupport.pro
+ testsupport_plugin.depends = qml_module
+ SUBDIRS += testsupport_plugin
}
-!build_pass {
- python = $$pythonPathForShell()
- chromium_attributions.commands = \
- cd $$shell_quote($$shell_path($$PWD/../3rdparty)) && \
- $$python chromium/tools/licenses.py \
- --file-template ../../tools/about_credits.tmpl \
- --entry-template ../../tools/about_credits_entry.tmpl credits \
- $$shell_quote($$shell_path($$OUT_PWD/chromium_attributions.qdoc))
- chromium_attributions.CONFIG += phony
-
- QMAKE_EXTRA_TARGETS += chromium_attributions
-
- prepare_docs {
- prepare_docs.depends += chromium_attributions
- } else {
- html_docs.depends += chromium_attributions
- }
+qtConfig(webengine-ui-delegates) {
+ SUBDIRS += ui \
+ ui2
}
-
-load(qt_module)
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 5da39e814..06a708672 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -48,7 +48,7 @@
#include "file_picker_controller.h"
#include "javascript_dialog_controller.h"
#if QT_CONFIG(webengine_printing_and_pdf)
-#include "printing/pdfium_document_wrapper_qt.h"
+#include "printer_worker.h"
#endif
#include "qwebenginecertificateerror.h"
#include "qwebenginefullscreenrequest.h"
@@ -94,6 +94,7 @@
#include <QMimeData>
#if QT_CONFIG(webengine_printing_and_pdf)
#include <QPrinter>
+#include <QThread>
#endif
#include <QStandardPaths>
#include <QStyle>
@@ -106,89 +107,6 @@ using namespace QtWebEngineCore;
static const int MaxTooltipLength = 1024;
-#if QT_CONFIG(webengine_printing_and_pdf)
-static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer)
-{
- if (!data.size()) {
- qWarning("Failure to print on printer %ls: Print result data is empty.",
- qUtf16Printable(printer.printerName()));
- return false;
- }
-
- QSize pageSize = printer.pageRect().size();
- PdfiumDocumentWrapperQt pdfiumWrapper(data.constData(), data.size(), pageSize);
-
- int toPage = printer.toPage();
- int fromPage = printer.fromPage();
- bool ascendingOrder = true;
-
- if (fromPage == 0 && toPage == 0) {
- fromPage = 1;
- toPage = pdfiumWrapper.pageCount();
- }
- fromPage = qMax(1, fromPage);
- toPage = qMin(pdfiumWrapper.pageCount(), toPage);
-
- if (printer.pageOrder() == QPrinter::LastPageFirst) {
- qSwap(fromPage, toPage);
- ascendingOrder = false;
- }
-
- int pageCopies = 1;
- int documentCopies = 1;
-
- if (!printer.supportsMultipleCopies())
- documentCopies = printer.copyCount();
-
- if (printer.collateCopies()) {
- pageCopies = documentCopies;
- documentCopies = 1;
- }
-
- QPainter painter;
- if (!painter.begin(&printer)) {
- qWarning("Failure to print on printer %ls: Could not open printer for painting.",
- qUtf16Printable(printer.printerName()));
- return false;
- }
-
- for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) {
- int currentPageIndex = fromPage;
- while (true) {
- for (int printedPages = 0; printedPages < pageCopies; printedPages++) {
- if (printer.printerState() == QPrinter::Aborted
- || printer.printerState() == QPrinter::Error)
- return false;
-
- QImage currentImage = pdfiumWrapper.pageAsQImage(currentPageIndex - 1);
- if (currentImage.isNull())
- return false;
-
- // Painting operations are automatically clipped to the bounds of the drawable part of the page.
- painter.drawImage(QRect(0, 0, pageSize.width(), pageSize.height()), currentImage, currentImage.rect());
- if (printedPages < pageCopies - 1)
- printer.newPage();
- }
-
- if (currentPageIndex == toPage)
- break;
-
- if (ascendingOrder)
- currentPageIndex++;
- else
- currentPageIndex--;
-
- printer.newPage();
- }
- if (printedDocuments < documentCopies - 1)
- printer.newPage();
- }
- painter.end();
-
- return true;
-}
-#endif // QT_CONFIG(webengine_printing_and_pdf)
-
static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition)
{
switch (disposition) {
@@ -241,6 +159,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
, webChannelWorldId(QWebEngineScript::MainWorld)
, defaultAudioMuted(false)
, defaultZoomFactor(1.0)
+ , requestInterceptor(nullptr)
#if QT_CONFIG(webengine_printing_and_pdf)
, currentPrinter(nullptr)
#endif
@@ -260,6 +179,8 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
QWebEnginePagePrivate::~QWebEnginePagePrivate()
{
+ if (requestInterceptor)
+ profile->d_ptr->profileAdapter()->removePageRequestInterceptor();
delete history;
delete settings;
}
@@ -499,19 +420,35 @@ void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount)
m_callbacks.invoke(requestId, matchCount > 0);
}
-void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &result)
+void QWebEnginePagePrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result)
{
#if QT_CONFIG(webengine_printing_and_pdf)
+ Q_Q(QWebEnginePage);
+
// If no currentPrinter is set that means that were printing to PDF only.
if (!currentPrinter) {
- m_callbacks.invoke(requestId, result);
+ if (!result.data())
+ return;
+ m_callbacks.invoke(requestId, *(result.data()));
return;
}
- bool printerResult = printPdfDataOnPrinter(result, *currentPrinter);
+ QThread *printerThread = new QThread;
+ QObject::connect(printerThread, &QThread::finished, printerThread, &QThread::deleteLater);
+ printerThread->start();
+
+ PrinterWorker *printerWorker = new PrinterWorker(result, currentPrinter);
+ QObject::connect(printerWorker, &PrinterWorker::resultReady, q, [=](bool success) {
+ currentPrinter = nullptr;
+ m_callbacks.invoke(requestId, success);
+ });
+
+ QObject::connect(printerWorker, &PrinterWorker::resultReady, printerThread, &QThread::quit);
+ QObject::connect(printerThread, &QThread::finished, printerWorker, &PrinterWorker::deleteLater);
+
+ printerWorker->moveToThread(printerThread);
+ QMetaObject::invokeMethod(printerWorker, "print");
- currentPrinter = nullptr;
- m_callbacks.invoke(requestId, printerResult);
#else
// we should never enter this branch, but just for safe-keeping...
Q_UNUSED(result);
@@ -1850,6 +1787,40 @@ void QWebEnginePagePrivate::printRequested()
});
}
+/*!
+ \since 5.13
+
+ Registers the request interceptor \a interceptor to intercept URL requests.
+
+ The page does not take ownership of the pointer. This interceptor is called
+ after any interceptors on the profile, and unlike profile interceptors, is run
+ on the UI thread, making it thread-safer. Only URL requests from this page are
+ intercepted.
+
+ To unset the request interceptor, set a \c nullptr.
+
+ \sa QWebEngineUrlRequestInfo, QWebEngineProfile::setRequestInterceptor()
+*/
+
+void QWebEnginePage::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
+{
+ Q_D(QWebEnginePage);
+ bool hadInterceptorChanged = bool(d->requestInterceptor) != bool(interceptor);
+ d->requestInterceptor = interceptor;
+ if (hadInterceptorChanged) {
+ if (interceptor)
+ d->profile->d_ptr->profileAdapter()->addPageRequestInterceptor();
+ else
+ d->profile->d_ptr->profileAdapter()->removePageRequestInterceptor();
+ }
+}
+
+void QWebEnginePagePrivate::interceptRequest(QWebEngineUrlRequestInfo &info)
+{
+ if (requestInterceptor)
+ requestInterceptor->interceptRequest(info);
+}
+
#if QT_CONFIG(menu)
QMenu *QWebEnginePage::createStandardContextMenu()
{
@@ -2434,10 +2405,7 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res
It is the users responsibility to ensure the \a printer remains valid until \a resultCallback
has been called.
- \note The rendering of the current content into a temporary PDF document is asynchronous and does
- not block the main thread. However, the subsequent rendering of PDF into \a printer runs on the
- main thread and will therefore block the event loop. Moreover, printing runs on the browser
- process, which is by default not sandboxed.
+ \note Printing runs on the browser process, which is by default not sandboxed.
The \a resultCallback must take a boolean as parameter. If printing was successful, this
boolean will have the value \c true, otherwise, its value will be \c false.
diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h
index 028f1a441..5eda8c72f 100644
--- a/src/webenginewidgets/api/qwebenginepage.h
+++ b/src/webenginewidgets/api/qwebenginepage.h
@@ -71,6 +71,7 @@ class QWebEngineQuotaRequest;
class QWebEngineRegisterProtocolHandlerRequest;
class QWebEngineScriptCollection;
class QWebEngineSettings;
+class QWebEngineUrlRequestInterceptor;
class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject {
Q_OBJECT
@@ -303,6 +304,8 @@ public:
void setDevToolsPage(QWebEnginePage *page);
QWebEnginePage *devToolsPage() const;
+ void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
+
const QWebEngineContextMenuData &contextMenuData() const;
Q_SIGNALS:
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index eecbf0b65..e60438d97 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -66,6 +66,8 @@
namespace QtWebEngineCore {
class RenderWidgetHostViewQtDelegate;
class RenderWidgetHostViewQtDelegateWidget;
+class TouchHandleDrawableClient;
+class TouchSelectionMenuController;
class WebContentsAdapter;
}
@@ -124,7 +126,7 @@ public:
void didFetchDocumentMarkup(quint64 requestId, const QString& result) override;
void didFetchDocumentInnerText(quint64 requestId, const QString& result) override;
void didFindText(quint64 requestId, int matchCount) override;
- void didPrintPage(quint64 requestId, const QByteArray &result) override;
+ void didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) override;
void didPrintPageToPdf(const QString &filePath, bool success) override;
void passOnFocus(bool reverse) override;
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override;
@@ -149,8 +151,12 @@ public:
bool isEnabled() const override;
void setToolTip(const QString &toolTipText) override;
void printRequested() override;
+ QtWebEngineCore::TouchHandleDrawableClient *createTouchHandle(const QMap<int, QImage> &) override { return nullptr; }
+ void showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *, const QRect &, const QSize &) override { }
+ void hideTouchSelectionMenu() override { }
const QObject *holdingQObject() const override;
ClientType clientType() override { return QtWebEngineCore::WebContentsAdapterClient::WidgetsClient; }
+ void interceptRequest(QWebEngineUrlRequestInfo &) override;
void widgetChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegate *newWidget) override;
QtWebEngineCore::ProfileAdapter *profileAdapter() override;
@@ -193,6 +199,7 @@ public:
bool defaultAudioMuted;
qreal defaultZoomFactor;
QTimer wasShownTimer;
+ QWebEngineUrlRequestInterceptor *requestInterceptor;
QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget *widget = nullptr;
mutable QtWebEngineCore::CallbackDirectory m_callbacks;
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index 03ce5e0bc..7e80f9720 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -359,6 +359,34 @@ void QWebEngineProfile::setPersistentStoragePath(const QString &path)
}
/*!
+ \since 5.13
+
+ The path to the location where the downloaded files are stored.
+
+ \note By default, the download path is QStandardPaths::DownloadLocation.
+
+ \sa setDownloadPath(), QStandardPaths::writableLocation()
+*/
+QString QWebEngineProfile::downloadPath() const
+{
+ const Q_D(QWebEngineProfile);
+ return d->profileAdapter()->downloadPath();
+}
+
+/*!
+ Overrides the default path used for download location, setting it to \a path.
+
+ If set to the null string, the default path is restored.
+
+ \sa downloadPath()
+*/
+void QWebEngineProfile::setDownloadPath(const QString &path)
+{
+ Q_D(QWebEngineProfile);
+ d->profileAdapter()->setDownloadPath(path);
+}
+
+/*!
Returns the path used for caches.
By default, this is below StandardPaths::CacheLocation in a QtWebengine/StorageName specific
@@ -668,20 +696,7 @@ QWebEngineSettings *QWebEngineProfile::settings() const
const QWebEngineUrlSchemeHandler *QWebEngineProfile::urlSchemeHandler(const QByteArray &scheme) const
{
const Q_D(QWebEngineProfile);
- if (d->profileAdapter()->customUrlSchemeHandlers().contains(scheme))
- return d->profileAdapter()->customUrlSchemeHandlers().value(scheme);
- return 0;
-}
-
-static bool checkInternalScheme(const QByteArray &scheme)
-{
- static QSet<QByteArray> internalSchemes;
- if (internalSchemes.isEmpty()) {
- internalSchemes << QByteArrayLiteral("qrc") << QByteArrayLiteral("data") << QByteArrayLiteral("blob")
- << QByteArrayLiteral("http") << QByteArrayLiteral("https") << QByteArrayLiteral("ftp")
- << QByteArrayLiteral("javascript");
- }
- return internalSchemes.contains(scheme);
+ return d->profileAdapter()->urlSchemeHandler(scheme);
}
/*!
@@ -695,25 +710,7 @@ static bool checkInternalScheme(const QByteArray &scheme)
void QWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler)
{
Q_D(QWebEngineProfile);
- Q_ASSERT(handler);
- QByteArray canonicalScheme = scheme.toLower();
- if (checkInternalScheme(canonicalScheme)) {
- qWarning("Cannot install a URL scheme handler overriding internal scheme: %s", scheme.constData());
- return;
- }
-
- if (d->profileAdapter()->customUrlSchemeHandlers().contains(canonicalScheme)) {
- if (d->profileAdapter()->customUrlSchemeHandlers().value(canonicalScheme) != handler)
- qWarning("URL scheme handler already installed for the scheme: %s", scheme.constData());
- return;
- }
-
- if (QWebEngineUrlScheme::schemeByName(canonicalScheme) == QWebEngineUrlScheme())
- qWarning("Please register the custom scheme '%s' via QWebEngineUrlScheme::registerScheme() "
- "before installing the custom scheme handler.", scheme.constData());
-
- d->profileAdapter()->addCustomUrlSchemeHandler(canonicalScheme, handler);
- connect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)));
+ d->profileAdapter()->installUrlSchemeHandler(scheme, handler);
}
/*!
@@ -726,10 +723,7 @@ void QWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, QWebEn
void QWebEngineProfile::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler)
{
Q_D(QWebEngineProfile);
- Q_ASSERT(handler);
- if (!d->profileAdapter()->removeCustomUrlSchemeHandler(handler))
- return;
- disconnect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)));
+ d->profileAdapter()->removeUrlSchemeHandler(handler);
}
/*!
@@ -742,10 +736,7 @@ void QWebEngineProfile::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handl
void QWebEngineProfile::removeUrlScheme(const QByteArray &scheme)
{
Q_D(QWebEngineProfile);
- QWebEngineUrlSchemeHandler *handler = d->profileAdapter()->takeCustomUrlSchemeHandler(scheme);
- if (!handler)
- return;
- disconnect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)));
+ d->profileAdapter()->removeUrlScheme(scheme);
}
/*!
@@ -756,12 +747,42 @@ void QWebEngineProfile::removeUrlScheme(const QByteArray &scheme)
void QWebEngineProfile::removeAllUrlSchemeHandlers()
{
Q_D(QWebEngineProfile);
- d->profileAdapter()->clearCustomUrlSchemeHandlers();
+ d->profileAdapter()->removeAllUrlSchemeHandlers();
}
-void QWebEngineProfile::destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *obj)
+/*!
+ \since 5.13
+
+ Sets this profile to be used for downloading and caching when needed during
+ certificate verification, for instance for OCSP, CRLs, and AIA.
+
+ Only one QWebEngineProfile can do this at a time, and it is recommended
+ that the profile fullfilling this role has a disk HTTP cache to avoid
+ needlessly re-downloading.
+
+ Currently only affects Linux/NSS installations where it enables OCSP.
+
+ As long as one profile has this option enabled, all other profiles will be
+ able to use it for their certificate verification.
+
+ \sa isUsedForGlobalCertificateVerification(), httpCacheType()
+*/
+void QWebEngineProfile::setUseForGlobalCertificateVerification()
{
- removeUrlSchemeHandler(obj);
+ Q_D(QWebEngineProfile);
+ d->profileAdapter()->setUseForGlobalCertificateVerification();
+}
+
+/*!
+ \since 5.13
+
+ Returns \c true if this profile is currently being used for global
+ certificate verification.
+*/
+bool QWebEngineProfile::isUsedForGlobalCertificateVerification() const
+{
+ Q_D(const QWebEngineProfile);
+ return d->profileAdapter()->isUsedForGlobalCertificateVerification();
}
/*!
diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h
index f9a564cd2..9fc509851 100644
--- a/src/webenginewidgets/api/qwebengineprofile.h
+++ b/src/webenginewidgets/api/qwebengineprofile.h
@@ -128,19 +128,23 @@ public:
void setSpellCheckEnabled(bool enabled);
bool isSpellCheckEnabled() const;
+ void setUseForGlobalCertificateVerification();
+ bool isUsedForGlobalCertificateVerification() const;
+
+ QString downloadPath() const;
+ void setDownloadPath(const QString &path);
+
static QWebEngineProfile *defaultProfile();
Q_SIGNALS:
void downloadRequested(QWebEngineDownloadItem *download);
-private Q_SLOTS:
- void destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *obj);
-
private:
Q_DISABLE_COPY(QWebEngineProfile)
Q_DECLARE_PRIVATE(QWebEngineProfile)
QWebEngineProfile(QWebEngineProfilePrivate *, QObject *parent = Q_NULLPTR);
+ friend class QWebEnginePage;
friend class QWebEnginePagePrivate;
friend class QWebEngineUrlSchemeHandler;
QScopedPointer<QWebEngineProfilePrivate> d_ptr;
diff --git a/src/webenginewidgets/printer_worker.cpp b/src/webenginewidgets/printer_worker.cpp
new file mode 100644
index 000000000..3a670ad49
--- /dev/null
+++ b/src/webenginewidgets/printer_worker.cpp
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "printer_worker.h"
+
+#include "printing/pdfium_document_wrapper_qt.h"
+
+#include <QPainter>
+#include <QPrinter>
+
+namespace QtWebEngineCore {
+
+PrinterWorker::PrinterWorker(QSharedPointer<QByteArray> data, QPrinter *printer)
+ : m_data(data)
+ , m_printer(printer)
+{
+}
+
+PrinterWorker::~PrinterWorker()
+{
+}
+
+void PrinterWorker::print()
+{
+ if (!m_data->size()) {
+ qWarning("Failure to print on printer %ls: Print result data is empty.",
+ qUtf16Printable(m_printer->printerName()));
+ Q_EMIT resultReady(false);
+ return;
+ }
+
+ QSize pageSize = m_printer->pageRect().size();
+ PdfiumDocumentWrapperQt pdfiumWrapper(m_data->constData(), m_data->size(), pageSize);
+
+ int toPage = m_printer->toPage();
+ int fromPage = m_printer->fromPage();
+ bool ascendingOrder = true;
+
+ if (fromPage == 0 && toPage == 0) {
+ fromPage = 1;
+ toPage = pdfiumWrapper.pageCount();
+ }
+ fromPage = qMax(1, fromPage);
+ toPage = qMin(pdfiumWrapper.pageCount(), toPage);
+
+ if (m_printer->pageOrder() == QPrinter::LastPageFirst) {
+ qSwap(fromPage, toPage);
+ ascendingOrder = false;
+ }
+
+ int pageCopies = 1;
+ int documentCopies = 1;
+
+ if (!m_printer->supportsMultipleCopies())
+ documentCopies = m_printer->copyCount();
+
+ if (m_printer->collateCopies()) {
+ pageCopies = documentCopies;
+ documentCopies = 1;
+ }
+
+ QPainter painter;
+ if (!painter.begin(m_printer)) {
+ qWarning("Failure to print on printer %ls: Could not open printer for painting.",
+ qUtf16Printable(m_printer->printerName()));
+ Q_EMIT resultReady(false);
+ return;
+ }
+
+ for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) {
+ int currentPageIndex = fromPage;
+ while (true) {
+ for (int printedPages = 0; printedPages < pageCopies; printedPages++) {
+ if (m_printer->printerState() == QPrinter::Aborted
+ || m_printer->printerState() == QPrinter::Error) {
+ Q_EMIT resultReady(false);
+ return;
+ }
+
+ QImage currentImage = pdfiumWrapper.pageAsQImage(currentPageIndex - 1);
+ if (currentImage.isNull()) {
+ Q_EMIT resultReady(false);
+ return;
+ }
+
+ // Painting operations are automatically clipped to the bounds of the drawable part of the page.
+ painter.drawImage(QRect(0, 0, pageSize.width(), pageSize.height()), currentImage, currentImage.rect());
+ if (printedPages < pageCopies - 1)
+ m_printer->newPage();
+ }
+
+ if (currentPageIndex == toPage)
+ break;
+
+ if (ascendingOrder)
+ currentPageIndex++;
+ else
+ currentPageIndex--;
+
+ m_printer->newPage();
+ }
+ if (printedDocuments < documentCopies - 1)
+ m_printer->newPage();
+ }
+ painter.end();
+
+ Q_EMIT resultReady(true);
+ return;
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/webenginewidgets/printer_worker.h b/src/webenginewidgets/printer_worker.h
new file mode 100644
index 000000000..96025c90e
--- /dev/null
+++ b/src/webenginewidgets/printer_worker.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef PRINTER_WORKER_H
+#define PRINTER_WORKER_H
+
+#include "qtwebenginecoreglobal_p.h"
+
+#include <QSharedPointer>
+
+QT_BEGIN_NAMESPACE
+class QPrinter;
+QT_END_NAMESPACE
+
+namespace QtWebEngineCore {
+
+class PrinterWorker : public QObject
+{
+ Q_OBJECT
+public:
+ PrinterWorker(QSharedPointer<QByteArray> data, QPrinter *printer);
+ virtual ~PrinterWorker();
+
+public Q_SLOTS:
+ void print();
+
+Q_SIGNALS:
+ void resultReady(bool success);
+
+private:
+ Q_DISABLE_COPY(PrinterWorker)
+
+ QSharedPointer<QByteArray> m_data;
+ QPrinter *m_printer;
+};
+
+} // namespace QtWebEngineCore
+
+Q_DECLARE_METATYPE(QtWebEngineCore::PrinterWorker*)
+
+#endif // PRINTER_WORKER_H
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 900ed3324..5b464a461 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -132,25 +132,31 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende
"QSurfaceFormat before the QtGui application instance is created.");
}
#endif
-
- // Make sure the OpenGL profile of the QQuickWidget matches the shared context profile.
- if (sharedFormat.profile() == QSurfaceFormat::CoreProfile) {
- int major;
- int minor;
- QSurfaceFormat::OpenGLContextProfile profile;
-
+ int major;
+ int minor;
+ QSurfaceFormat::OpenGLContextProfile profile;
#ifdef Q_OS_MACOS
- // Due to QTBUG-63180, requesting the sharedFormat.majorVersion() on macOS will lead to
- // a failed creation of QQuickWidget shared context. Thus make sure to request the
- // major version specified in the defaultFormat instead.
- major = defaultFormat.majorVersion();
- minor = defaultFormat.minorVersion();
- profile = defaultFormat.profile();
+ // Due to QTBUG-63180, requesting the sharedFormat.majorVersion() on macOS will lead to
+ // a failed creation of QQuickWidget shared context. Thus make sure to request the
+ // major version specified in the defaultFormat instead.
+ major = defaultFormat.majorVersion();
+ minor = defaultFormat.minorVersion();
+ profile = defaultFormat.profile();
#else
- major = sharedFormat.majorVersion();
- minor = sharedFormat.minorVersion();
- profile = sharedFormat.profile();
+ major = sharedFormat.majorVersion();
+ minor = sharedFormat.minorVersion();
+ profile = sharedFormat.profile();
+#endif
+
+ // Make sure the OpenGL profile of the QQuickWidget matches the shared context profile.
+ // It covers the following cases:
+ // 1) Desktop OpenGL Core Profile.
+ // 2) Windows ANGLE OpenGL ES profile.
+ if (sharedFormat.profile() == QSurfaceFormat::CoreProfile
+#ifdef Q_OS_WIN
+ || globalSharedContext->isOpenGLES()
#endif
+ ) {
format.setMajorVersion(major);
format.setMinorVersion(minor);
format.setProfile(profile);
diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro
index e61575d3a..4669c2bce 100644
--- a/src/webenginewidgets/webenginewidgets.pro
+++ b/src/webenginewidgets/webenginewidgets.pro
@@ -49,6 +49,9 @@ HEADERS = \
qtConfig(webengine-printing-and-pdf) {
QT += printsupport
+
+ SOURCES += printer_worker.cpp
+ HEADERS += printer_worker.h
}
load(qt_module)
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
index 23bf88417..7b7fec6f4 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -51,7 +51,9 @@ private Q_SLOTS:
void cleanupTestCase();
void interceptRequest();
void ipv6HostEncoding();
+ void requestedUrl_data();
void requestedUrl();
+ void setUrlSameUrl_data();
void setUrlSameUrl();
void firstPartyUrl();
void firstPartyUrlNestedIframes_data();
@@ -123,10 +125,7 @@ public:
// Skip import documents and sandboxed documents.
// See Document::SiteForCookies() in chromium/third_party/blink/renderer/core/dom/document.cc.
- //
- // TODO: Change this to empty URL during the next chromium update:
- // https://chromium-review.googlesource.com/c/chromium/src/+/1213082/
- return requestInfo.firstPartyUrl == QUrl("data:,");
+ return requestInfo.firstPartyUrl == QUrl("");
}
QList<RequestInfo> getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceType type)
@@ -249,14 +248,27 @@ void tst_QWebEngineUrlRequestInterceptor::ipv6HostEncoding()
QCOMPARE(contentProvider.requestedUrls.at(0), QUrl::fromEncoded("http://[::1]/test.xml"));
}
+void tst_QWebEngineUrlRequestInterceptor::requestedUrl_data()
+{
+ QTest::addColumn<bool>("interceptInPage");
+
+ QTest::newRow("Profile intercept") << false;
+ QTest::newRow("Page intercept") << true;
+}
+
void tst_QWebEngineUrlRequestInterceptor::requestedUrl()
{
+ QFETCH(bool, interceptInPage);
+
QWebEngineProfile profile;
profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
TestRequestInterceptor interceptor(/* intercept */ true);
- profile.setRequestInterceptor(&interceptor);
+ if (!interceptInPage)
+ profile.setRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
+ if (interceptInPage)
+ page.setRequestInterceptor(&interceptor);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.setUrl(QUrl("qrc:///resources/__placeholder__"));
@@ -273,19 +285,29 @@ void tst_QWebEngineUrlRequestInterceptor::requestedUrl()
QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
page.setUrl(QUrl("http://abcdef.abcdef"));
- QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 3, 12000);
+ QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 3, 15000);
QCOMPARE(interceptor.requestInfos.at(3).requestUrl, QUrl("http://abcdef.abcdef/"));
QCOMPARE(page.requestedUrl(), QUrl("qrc:///resources/__placeholder__"));
QCOMPARE(page.url(), QUrl("qrc:///resources/content.html"));
}
+void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl_data()
+{
+ requestedUrl_data();
+}
+
void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl()
{
+ QFETCH(bool, interceptInPage);
+
QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ true);
- profile.setRequestInterceptor(&interceptor);
+ if (!interceptInPage)
+ profile.setRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
+ if (interceptInPage)
+ page.setRequestInterceptor(&interceptor);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.setUrl(QUrl("qrc:///resources/__placeholder__"));
diff --git a/tests/auto/quick/dialogs/dialogs.pro b/tests/auto/quick/dialogs/dialogs.pro
index e262c3814..29d509b20 100644
--- a/tests/auto/quick/dialogs/dialogs.pro
+++ b/tests/auto/quick/dialogs/dialogs.pro
@@ -1,5 +1,5 @@
include(../tests.pri)
-QT += webengine webengine-private
+QT += core-private webengine webengine-private
HEADERS += \
server.h \
diff --git a/tests/auto/quick/dialogs/tst_dialogs.cpp b/tests/auto/quick/dialogs/tst_dialogs.cpp
index ecc2764fd..cecea1831 100644
--- a/tests/auto/quick/dialogs/tst_dialogs.cpp
+++ b/tests/auto/quick/dialogs/tst_dialogs.cpp
@@ -26,7 +26,6 @@
**
****************************************************************************/
-#include "qtwebengineglobal.h"
#include "testhandler.h"
#include "server.h"
#include <QtWebEngine/private/qquickwebenginedialogrequests_p.h>
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index 0e48e280d..4cbadfdaa 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -40,6 +40,7 @@
#include <private/qquickwebengineview_p.h>
#include <private/qquickwebengineaction_p.h>
#include <private/qquickwebenginecertificateerror_p.h>
+#include <private/qquickwebengineclientcertificateselection_p.h>
#include <private/qquickwebenginedialogrequests_p.h>
#include <private/qquickwebenginedownloaditem_p.h>
#include <private/qquickwebenginehistory_p.h>
@@ -60,6 +61,8 @@ static const QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *
<< &QQuickWebEngineView::staticMetaObject
<< &QQuickWebEngineAction::staticMetaObject
<< &QQuickWebEngineCertificateError::staticMetaObject
+ << &QQuickWebEngineClientCertificateOption::staticMetaObject
+ << &QQuickWebEngineClientCertificateSelection::staticMetaObject
<< &QQuickWebEngineDownloadItem::staticMetaObject
<< &QQuickWebEngineHistory::staticMetaObject
<< &QQuickWebEngineHistoryListModel::staticMetaObject
@@ -86,6 +89,8 @@ static QList<const char *> knownEnumNames = QList<const char *>();
static const QStringList hardcodedTypes = QStringList()
<< "QJSValue"
<< "QQmlListProperty<QQuickWebEngineScript>"
+ << "QQmlListProperty<QQuickWebEngineClientCertificateOption>"
+ << "const QQuickWebEngineClientCertificateOption*"
<< "QQmlWebChannel*"
// Ignore the testSupport types without making a fuss.
<< "QQuickWebEngineTestSupport*"
diff --git a/tests/auto/quick/qmltests/data/tst_download.qml b/tests/auto/quick/qmltests/data/tst_download.qml
index 019ebd9dc..5eb704cce 100644
--- a/tests/auto/quick/qmltests/data/tst_download.qml
+++ b/tests/auto/quick/qmltests/data/tst_download.qml
@@ -28,7 +28,8 @@
import QtQuick 2.0
import QtTest 1.0
-import QtWebEngine 1.5
+import QtWebEngine 1.9
+import Qt.labs.platform 1.0
TestWebEngineView {
id: webEngineView
@@ -42,6 +43,12 @@ TestWebEngineView {
property var downloadState: []
property var downloadInterruptReason: null
+ function urlToPath(url) {
+ var path = url.toString()
+ path = path.replace(/^(file:\/{2})/,"")
+ return path
+ }
+
SignalSpy {
id: downLoadRequestedSpy
target: testDownloadProfile
@@ -135,5 +142,16 @@ TestWebEngineView {
tryCompare(downloadState, "1", WebEngineDownloadItem.DownloadCancelled)
tryCompare(webEngineView, "downloadInterruptReason", WebEngineDownloadItem.UserCanceled)
}
+
+ function test_downloadLocation() {
+ var tmpPath = urlToPath(StandardPaths.writableLocation(StandardPaths.TempLocation));
+ var downloadPath = urlToPath(StandardPaths.writableLocation(StandardPaths.DownloadLocation));
+
+ testDownloadProfile.downloadPath = tmpPath;
+ compare(testDownloadProfile.downloadPath, tmpPath);
+
+ testDownloadProfile.downloadPath = downloadPath;
+ compare(testDownloadProfile.downloadPath, downloadPath);
+ }
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml
index dfcfd586f..1ec574fae 100644
--- a/tests/auto/quick/qmltests/data/tst_findText.qml
+++ b/tests/auto/quick/qmltests/data/tst_findText.qml
@@ -116,7 +116,7 @@ TestWebEngineView {
webEngineView.clear()
webEngineView.findText("bla", findFlags, webEngineView.findTextCallback)
- tryCompare(webEngineView, "matchCount", 100)
+ tryCompare(webEngineView, "matchCount", 100, 20000)
verify(!findFailed)
}
@@ -172,7 +172,7 @@ TestWebEngineView {
webEngineView.clear()
webEngineView.findText("hello", findFlags, webEngineView.findTextCallback)
- tryCompare(webEngineView, "matchCount", 0)
+ tryCompare(webEngineView, "matchCount", 0, 20000)
verify(findFailed)
runJavaScript("document.body.innerHTML = 'blahellobla'");
diff --git a/tests/auto/quick/qmltests/data/tst_profile.qml b/tests/auto/quick/qmltests/data/tst_profile.qml
new file mode 100644
index 000000000..ee7fa4e99
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_profile.qml
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebEngine 1.9
+
+TestWebEngineView {
+ id: webEngineView
+ width: 400
+ height: 300
+
+
+ WebEngineProfile {
+ id: profile1
+ }
+ WebEngineProfile {
+ id: profile2
+ }
+ property bool profile1UsedForGlobalCertificateVerification: profile1.useForGlobalCertificateVerification
+
+ TestCase {
+ name: "WebEngineProfile"
+
+ function test_useForGlobalCertificateVerification() {
+ verify(!profile1.useForGlobalCertificateVerification);
+ verify(!profile2.useForGlobalCertificateVerification);
+ verify(!webEngineView.profile1UsedForGlobalCertificateVerification);
+
+ profile1.useForGlobalCertificateVerification = true;
+ verify(profile1.useForGlobalCertificateVerification);
+ verify(!profile2.useForGlobalCertificateVerification);
+ verify(webEngineView.profile1UsedForGlobalCertificateVerification);
+
+ profile2.useForGlobalCertificateVerification = true;
+ verify(!webEngineView.profile1UsedForGlobalCertificateVerification);
+ verify(!profile1.useForGlobalCertificateVerification);
+ verify(profile2.useForGlobalCertificateVerification);
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index a2b05e091..ad479cd31 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -67,6 +67,7 @@ OTHER_FILES += \
$$PWD/data/tst_navigationHistory.qml \
$$PWD/data/tst_navigationRequested.qml \
$$PWD/data/tst_newViewRequest.qml \
+ $$PWD/data/tst_profile.qml \
$$PWD/data/tst_properties.qml \
$$PWD/data/tst_runJavaScript.qml \
$$PWD/data/tst_scrollPosition.qml \
diff --git a/tests/auto/quick/qquickwebengineview/BLACKLIST b/tests/auto/quick/qquickwebengineview/BLACKLIST
index 76cb18c1e..5bb38576a 100644
--- a/tests/auto/quick/qquickwebengineview/BLACKLIST
+++ b/tests/auto/quick/qquickwebengineview/BLACKLIST
@@ -9,8 +9,13 @@ windows
[basicRenderingSanity]
*
+
[javascriptClipboard:default]
opensuse-leap
+
[javascriptClipboard:canPaste]
opensuse-leap
+[changeLocale]
+*
+
diff --git a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro
index c253bc2a6..38c130aa3 100644
--- a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro
+++ b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro
@@ -1,6 +1,6 @@
include(../tests.pri)
exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc
-QT_PRIVATE += webengine-private gui-private webenginecore-private
+QT_PRIVATE += core_private gui-private webengine-private webenginecore-private
HEADERS += ../shared/util.h
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index 007acb8b0..8947bba9d 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -31,6 +31,7 @@
#include <QScopedPointer>
#include <QtCore/qelapsedtimer.h>
+#include <QtCore/qregularexpression.h>
#include <QtGui/qclipboard.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
@@ -40,6 +41,7 @@
#include <QtGui/private/qinputmethod_p.h>
#include <QtWebEngine/private/qquickwebengineview_p.h>
#include <QtWebEngine/private/qquickwebenginesettings_p.h>
+#include <QtWebEngineCore/private/qtwebenginecore-config_p.h>
#include <qpa/qplatforminputcontext.h>
#include <functional>
@@ -1000,8 +1002,8 @@ void tst_QQuickWebEngineView::changeLocale()
QVERIFY(waitForLoadFailed(viewDE.data()));
QTRY_VERIFY(!evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").isNull());
- errorLines = evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").toString().split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
- QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar"));
+ errorLines = evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").toString().split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
+ QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar Die Server-IP-Adresse von non.existent wurde nicht gefunden."));
QLocale::setDefault(QLocale("en"));
QScopedPointer<QQuickWebEngineView> viewEN(newWebEngineView());
@@ -1009,7 +1011,7 @@ void tst_QQuickWebEngineView::changeLocale()
QVERIFY(waitForLoadFailed(viewEN.data()));
QTRY_VERIFY(!evaluateJavaScriptSync(viewEN.data(), "document.body.innerText").isNull());
- errorLines = evaluateJavaScriptSync(viewEN.data(), "document.body.innerText").toString().split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
+ errorLines = evaluateJavaScriptSync(viewEN.data(), "document.body.innerText").toString().split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("This site can\xE2\x80\x99t be reached"));
// Reset error page
@@ -1021,7 +1023,7 @@ void tst_QQuickWebEngineView::changeLocale()
QVERIFY(waitForLoadFailed(viewDE.data()));
QTRY_VERIFY(!evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").isNull());
- errorLines = evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").toString().split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
+ errorLines = evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").toString().split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar"));
}
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 50a6a8587..46dd57f76 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -1,5 +1,5 @@
-include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) # workaround for QTBUG-68093
-QT_FOR_CONFIG += webenginecore-private
+include($$QTWEBENGINE_OUT_ROOT/src/webengine/qtwebengine-config.pri) # workaround for QTBUG-68093
+QT_FOR_CONFIG += webengine-private
TEMPLATE = subdirs
diff --git a/tests/auto/quick/tests.pri b/tests/auto/quick/tests.pri
index f7104ad9c..1bf69da43 100644
--- a/tests/auto/quick/tests.pri
+++ b/tests/auto/quick/tests.pri
@@ -1,5 +1,5 @@
-include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) # workaround for QTBUG-68093
-QT_FOR_CONFIG += webenginecore-private
+include($$QTWEBENGINE_OUT_ROOT/src/webengine/qtwebengine-config.pri) # workaround for QTBUG-68093
+QT_FOR_CONFIG += webengine-private
TEMPLATE = app
diff --git a/tests/auto/widgets/origins/tst_origins.cpp b/tests/auto/widgets/origins/tst_origins.cpp
index 4e415af90..61c7232b0 100644
--- a/tests/auto/widgets/origins/tst_origins.cpp
+++ b/tests/auto/widgets/origins/tst_origins.cpp
@@ -301,7 +301,7 @@ void tst_Origins::jsUrlOrigin()
QCOMPARE(eval(QSL("new URL(\"qrc:/crysis.css\").origin")), QVariant(QSL("qrc://")));
QCOMPARE(eval(QSL("new URL(\"qrc://foo.com/crysis.css\").origin")), QVariant(QSL("qrc://")));
- // Same with unregistered schemes.
+ // Unregistered schemes behaves like opaque origins.
QCOMPARE(eval(QSL("new URL(\"tst:/banana\").origin")), QVariant(QSL("tst://")));
QCOMPARE(eval(QSL("new URL(\"tst://foo.com/banana\").origin")), QVariant(QSL("tst://")));
@@ -564,8 +564,6 @@ private:
// Try opening a WebSocket from pages loaded over various URL schemes.
void tst_Origins::webSocket()
{
- const int kAbnormalClosure = 1006;
-
EchoServer echoServer;
QWebChannel channel;
channel.registerObject(QSL("echoServer"), &echoServer);
@@ -578,9 +576,9 @@ void tst_Origins::webSocket()
QVERIFY(load(QSL("qrc:/resources/websocket.html")));
QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
- // Only registered schemes can open WebSockets.
+ // Unregistered schemes can also open WebSockets (since Chromium 71)
QVERIFY(load(QSL("tst:/resources/websocket.html")));
- QTRY_COMPARE(eval(QSL("result")), QVariant(kAbnormalClosure));
+ QTRY_COMPARE(eval(QSL("result")), QVariant(QSL("ok")));
// Even an insecure registered scheme can open WebSockets.
QVERIFY(load(QSL("PathSyntax:/resources/websocket.html")));
@@ -599,11 +597,10 @@ void tst_Origins::dedicatedWorker()
QTRY_VERIFY(eval(QSL("done")).toBool());
QCOMPARE(eval(QSL("result")), QVariant(42));
- // Unregistered schemes cannot create Workers.
+ // Unregistered schemes can also create Workers (since Chromium 71)
QVERIFY(load(QSL("tst:/resources/dedicatedWorker.html")));
QTRY_VERIFY(eval(QSL("done")).toBool());
- QVERIFY(eval(QSL("error")).toString()
- .contains(QSL("Access to dedicated workers is denied to origin 'tst://'")));
+ QCOMPARE(eval(QSL("result")), QVariant(42));
// Even an insecure registered scheme can create Workers.
QVERIFY(load(QSL("PathSyntax:/resources/dedicatedWorker.html")));
@@ -727,15 +724,9 @@ void tst_Origins::createObjectURL()
QVERIFY(load(QSL("qrc:/resources/createObjectURL.html")));
QVERIFY(eval(QSL("result")).toString().startsWith(QSL("blob:qrc:")));
- // Illegal for unregistered schemes (renderer gets terminated).
- qRegisterMetaType<QWebEnginePage::RenderProcessTerminationStatus>("RenderProcessTerminationStatus");
- QSignalSpy loadFinishedSpy(m_page, &QWebEnginePage::loadFinished);
- QSignalSpy renderProcessTerminatedSpy(m_page, &QWebEnginePage::renderProcessTerminated);
- m_page->load(QSL("tst:/resources/createObjectURL.html"));
- QVERIFY(!renderProcessTerminatedSpy.empty() || renderProcessTerminatedSpy.wait(20000));
- QVERIFY(renderProcessTerminatedSpy.front().value(0).value<QWebEnginePage::RenderProcessTerminationStatus>()
- != QWebEnginePage::NormalTerminationStatus);
- QVERIFY(loadFinishedSpy.empty());
+ // Also legal for unregistered schemes (since Chromium 71)
+ QVERIFY(load(QSL("tst:/resources/createObjectURL.html")));
+ QVERIFY(eval(QSL("result")).toString().startsWith(QSL("blob:tst:")));
}
QTEST_MAIN(tst_Origins)
diff --git a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
index 2af818928..b50036aa8 100644
--- a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
+++ b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
@@ -31,6 +31,7 @@
#include <QStandardPaths>
#include <QTemporaryDir>
#include <QTest>
+#include <QRegularExpression>
#include <QWebEngineDownloadItem>
#include <QWebEnginePage>
#include <QWebEngineProfile>
@@ -69,6 +70,12 @@ private Q_SLOTS:
void downloadFileNot1();
void downloadFileNot2();
void downloadDeleted();
+ void downloadUniqueFilename_data();
+ void downloadUniqueFilename();
+ void downloadUniqueFileNameWithTimeStamp();
+ void downloadToDefaultLocation();
+ void downloadToNonExistentDir();
+ void downloadToReadOnlyDir();
private:
void saveLink(QPoint linkPos);
@@ -134,6 +141,8 @@ void tst_QWebEngineDownloadItem::cleanup()
QTRY_COMPARE(m_requestedDownloads.count(), 0);
QCOMPARE(m_finishedDownloads.count(), 0);
QVERIFY(m_server->stop());
+ // Set download path to default.
+ m_profile->setDownloadPath("");
}
void tst_QWebEngineDownloadItem::cleanupTestCase()
@@ -611,6 +620,7 @@ void tst_QWebEngineDownloadItem::downloadPage_data()
void tst_QWebEngineDownloadItem::downloadPage()
{
+ QSKIP("Unstable since Chromium 71");
QFETCH(QWebEngineDownloadItem::SavePageFormat, savePageFormat);
// Set up HTTP server
@@ -812,5 +822,264 @@ void tst_QWebEngineDownloadItem::downloadDeleted()
QTRY_COMPARE(finishedCount, 1);
}
+void tst_QWebEngineDownloadItem::downloadUniqueFilename_data()
+{
+ QTest::addColumn<QString>("baseName");
+ QTest::addColumn<QString>("extension");
+
+ QTest::newRow("txt") << QString("test(1.test)") << QString("txt");
+ QTest::newRow("tar.gz") << QString("test(1.test)") << QString("tar.gz");
+}
+
+void tst_QWebEngineDownloadItem::downloadUniqueFilename()
+{
+ QFETCH(QString, baseName);
+ QFETCH(QString, extension);
+ QString fileName = QString("%1.%2").arg(baseName).arg(extension);
+ QString downloadedFilePath;
+ bool downloadFinished = false;
+
+ QTemporaryDir tmpDir;
+ QVERIFY(tmpDir.isValid());
+ m_profile->setDownloadPath(tmpDir.path());
+
+ // Set up HTTP server
+ ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) {
+ if (rr->requestMethod() == "GET" && rr->requestPath() == ("/" + fileName)) {
+ rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("application/octet-stream"));
+ rr->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment"));
+ rr->setResponseBody(QByteArrayLiteral("a"));
+ rr->sendResponse();
+ } else {
+ rr->setResponseStatus(404);
+ rr->sendResponse();
+ }
+ });
+
+ // Set up profile and download handler
+ ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) {
+ item->accept();
+ connect(item, &QWebEngineDownloadItem::finished, [&, item]() {
+ QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadCompleted);
+ QCOMPARE(item->isFinished(), true);
+ QCOMPARE(item->totalBytes(), item->receivedBytes());
+ QVERIFY(item->receivedBytes() > 0);
+ QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason);
+ QCOMPARE(item->type(), QWebEngineDownloadItem::Attachment);
+ QCOMPARE(item->isSavePageDownload(), false);
+ downloadedFilePath = item->path();
+ downloadFinished = true;
+ });
+ });
+
+ m_page->setUrl(m_server->url("/" + fileName));
+ QTRY_VERIFY(downloadFinished);
+ QVERIFY(QFile(downloadedFilePath).exists());
+ QCOMPARE(downloadedFilePath, m_profile->downloadPath() + "/" + baseName + "." + extension);
+
+ for (int i = 1; i <= 2; ++i) {
+ downloadFinished = false;
+ m_page->setUrl(m_server->url("/" + fileName));
+ QTRY_VERIFY(downloadFinished);
+ QVERIFY(QFile(downloadedFilePath).exists());
+ QCOMPARE(downloadedFilePath, m_profile->downloadPath() + "/" + baseName + " (" + QString::number(i) + ")." + extension);
+ }
+}
+
+void tst_QWebEngineDownloadItem::downloadUniqueFileNameWithTimeStamp()
+{
+ // Set up HTTP server
+ QString baseName("test(1.test)");
+ QString extension("txt");
+ QString fileName = QString("%1.%2").arg(baseName).arg(extension);
+ QString downloadedFilePath;
+ bool downloadFinished = false;
+
+ QTemporaryDir tmpDir;
+ QVERIFY(tmpDir.isValid());
+ m_profile->setDownloadPath(tmpDir.path());
+
+ ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) {
+ if (rr->requestMethod() == "GET" && rr->requestPath() == ("/" + fileName)) {
+ rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("application/octet-stream"));
+ rr->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment"));
+ rr->setResponseBody(QByteArrayLiteral("a"));
+ rr->sendResponse();
+ } else {
+ rr->setResponseStatus(404);
+ rr->sendResponse();
+ }
+ });
+
+ // Set up profile and download handler
+ ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) {
+ item->accept();
+ connect(item, &QWebEngineDownloadItem::finished, [&, item]() {
+ QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadCompleted);
+ QCOMPARE(item->isFinished(), true);
+ QCOMPARE(item->totalBytes(), item->receivedBytes());
+ QVERIFY(item->receivedBytes() > 0);
+ QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason);
+ QCOMPARE(item->page(), m_page);
+ downloadFinished = true;
+ downloadedFilePath = item->path();
+ });
+ });
+
+ // Create the first empty file without uniquifier.
+ {
+ QFile file(m_profile->downloadPath() + "/" + fileName);
+ file.open(QIODevice::ReadWrite);
+ }
+
+ // Create 99 empty files with uniquifier.
+ for (int i = 1; i < 100; i++) {
+ QFile file(m_profile->downloadPath() + "/" + baseName + " (" + QString::number(i) + ")." + extension);
+ file.open(QIODevice::ReadWrite);
+ }
+
+ // Create 100th (kMaxUniqueFiles) empty file with uniquifier.
+ m_page->setUrl(m_server->url("/" + fileName));
+ QTRY_VERIFY(downloadFinished);
+ QVERIFY(QFile(downloadedFilePath).exists());
+ QCOMPARE(downloadedFilePath, m_profile->downloadPath() + "/" + baseName + " (100)." + extension);
+
+ // Check if the downloaded files are suffixed with timestamp after the 100th download.
+ for (int i = 101; i < 103; i++) {
+ downloadFinished = false;
+ m_page->setUrl(m_server->url("/" + fileName));
+ QTRY_VERIFY(downloadFinished);
+ QVERIFY(QFile(downloadedFilePath).exists());
+ QRegularExpression fileNameCheck("^.*" + QRegularExpression::escape(baseName) + " - (.*)[.]" + QRegularExpression::escape(extension) + "$");
+ QRegularExpressionMatch match = fileNameCheck.match(downloadedFilePath);
+ QVERIFY(match.hasMatch());
+ // ISO 8601 Date and time in UTC
+ QRegExp timeStamp("^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])([.][0-9]+)?(Z|[+-](?:2[0-3]|[01][0-9]):[0-5][0-9])?$");
+ QVERIFY(timeStamp.exactMatch(match.captured(1)));
+ }
+}
+
+void tst_QWebEngineDownloadItem::downloadToDefaultLocation()
+{
+ QTemporaryDir tmpDir;
+ QVERIFY(tmpDir.isValid());
+
+ QCOMPARE(m_profile->downloadPath(), QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
+
+ m_profile->setDownloadPath("");
+ QCOMPARE(m_profile->downloadPath(), QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
+
+ m_profile->setDownloadPath(tmpDir.path());
+ QCOMPARE(m_profile->downloadPath(), tmpDir.path());
+
+ m_profile->setDownloadPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
+ QCOMPARE(m_profile->downloadPath(), QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
+}
+
+void tst_QWebEngineDownloadItem::downloadToNonExistentDir()
+{
+ QString baseName("test(1.test)");
+ QString extension("txt");
+ QString fileName = QString("%1.%2").arg(baseName).arg(extension);
+ QString downloadedFilePath;
+ bool downloadFinished = false;
+
+ QTemporaryDir tmpDir;
+ QVERIFY(tmpDir.isValid());
+ m_profile->setDownloadPath(tmpDir.path());
+
+ // Set up HTTP server
+ ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) {
+ if (rr->requestMethod() == "GET" && rr->requestPath() == ("/" + fileName)) {
+ rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("application/octet-stream"));
+ rr->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment"));
+ rr->setResponseBody(QByteArrayLiteral("a"));
+ rr->sendResponse();
+ } else {
+ rr->setResponseStatus(404);
+ rr->sendResponse();
+ }
+ });
+
+ // Set up profile and download handler
+ ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) {
+ item->accept();
+ connect(item, &QWebEngineDownloadItem::finished, [&, item]() {
+ QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadCompleted);
+ QCOMPARE(item->isFinished(), true);
+ QCOMPARE(item->totalBytes(), item->receivedBytes());
+ QVERIFY(item->receivedBytes() > 0);
+ QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason);
+ QCOMPARE(item->page(), m_page);
+ downloadFinished = true;
+ downloadedFilePath = item->path();
+ });
+ });
+
+ // Set a non-existent directory for the default download location.
+ QString nonExistentDownloadPath(m_profile->downloadPath() + "/non_existent_dir");
+ m_profile->setDownloadPath(nonExistentDownloadPath);
+ QCOMPARE(m_profile->downloadPath(), nonExistentDownloadPath);
+ m_page->setUrl(m_server->url("/" + fileName));
+ QTRY_VERIFY(downloadFinished);
+ QVERIFY(QFile(downloadedFilePath).exists());
+ QCOMPARE(downloadedFilePath, nonExistentDownloadPath + "/" + fileName);
+}
+
+void tst_QWebEngineDownloadItem::downloadToReadOnlyDir()
+{
+ QString baseName("test(1.test)");
+ QString extension("txt");
+ QString fileName = QString("%1.%2").arg(baseName).arg(extension);
+ QString downloadedFilePath;
+ bool downloadAccepted = false;
+ bool downloadFinished = false;
+
+ QTemporaryDir tmpDir;
+ QVERIFY(tmpDir.isValid());
+ m_profile->setDownloadPath(tmpDir.path());
+
+ // Set up HTTP server
+ ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) {
+ if (rr->requestMethod() == "GET" && rr->requestPath() == ("/" + fileName)) {
+ rr->setResponseHeader(QByteArrayLiteral("content-type"), QByteArrayLiteral("application/octet-stream"));
+ rr->setResponseHeader(QByteArrayLiteral("content-disposition"), QByteArrayLiteral("attachment"));
+ rr->setResponseBody(QByteArrayLiteral("a"));
+ rr->sendResponse();
+ } else {
+ rr->setResponseStatus(404);
+ rr->sendResponse();
+ }
+ });
+
+ QPointer<QWebEngineDownloadItem> downloadItem;
+ ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) {
+ downloadItem = item;
+ item->accept();
+ connect(item, &QWebEngineDownloadItem::finished, [&, item]() {
+ downloadFinished = true;
+ });
+ downloadAccepted = true;
+ });
+
+ // Change permission for directory.
+ QFile(m_profile->downloadPath()).setPermissions(QFileDevice::ReadOwner);
+ QVERIFY(QFile(m_profile->downloadPath()).exists());
+
+ m_page->setUrl(m_server->url("/" + fileName));
+ QTRY_VERIFY(downloadAccepted);
+
+ QVERIFY(downloadItem);
+ QTRY_COMPARE(downloadItem->state(), QWebEngineDownloadItem::DownloadInterrupted);
+ QCOMPARE(downloadItem->isFinished(), false);
+ QCOMPARE(downloadItem->interruptReason(), QWebEngineDownloadItem::FileAccessDenied);
+ QVERIFY(!QFile(downloadedFilePath).exists());
+
+ // Clear m_requestedDownloads explicitly because download is accepted but never finished.
+ m_requestedDownloads.clear();
+ QVERIFY(!downloadFinished);
+ QFile(m_profile->downloadPath()).setPermissions(QFileDevice::WriteOwner);
+}
+
QTEST_MAIN(tst_QWebEngineDownloadItem)
#include "tst_qwebenginedownloaditem.moc"
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index fdff57254..0b519fe8a 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -34,7 +34,6 @@
#include <QOpenGLWidget>
#include <QPaintEngine>
#include <QPushButton>
-#include <QRegExp>
#include <QScreen>
#include <QStateMachine>
#include <QtGui/QClipboard>
@@ -90,11 +89,8 @@ public Q_SLOTS:
private Q_SLOTS:
void initTestCase();
void cleanupTestCase();
- void thirdPartyCookiePolicy();
void comboBoxPopupPositionAfterMove();
void comboBoxPopupPositionAfterChildMove();
- void contextMenuCopy();
- void contextMenuPopulatedOnce();
void acceptNavigationRequest();
void acceptNavigationRequestNavigationType();
void geolocationRequestJS_data();
@@ -103,26 +99,13 @@ private Q_SLOTS:
void actionStates();
void pasteImage();
void popupFormSubmission();
- void userStyleSheet();
- void userStyleSheetFromLocalFileUrl();
- void userStyleSheetFromQrcUrl();
- void modified();
- void contextMenuCrash();
- void updatePositionDependentActionsCrash();
void callbackSpyDeleted();
void multipleProfilesAndLocalStorage();
- void cursorMovements();
void textSelection();
- void textEditing();
void backActionUpdate();
- void testOptionalJSObjects();
- void testLocalStorageVisibility();
- void testEnablePersistentStorage();
+ void localStorageVisibility();
void consoleOutput();
- void errorPageExtension();
- void errorPageExtensionLoadFinished();
void userAgentNewlineStripping();
- void undoActionHaveCustomText();
void renderWidgetHostViewNotShowTopLevel();
void getUserMediaRequest_data();
void getUserMediaRequest();
@@ -134,30 +117,19 @@ private Q_SLOTS:
void crashTests_LazyInitializationOfMainFrame();
- void screenshot_data();
- void screenshot();
-
#if defined(ENABLE_WEBGL) && ENABLE_WEBGL
void acceleratedWebGLScreenshotWithoutView();
void unacceleratedWebGLScreenshotWithoutView();
#endif
void testJSPrompt();
- void testStopScheduledPageRefresh();
void findText();
void findTextResult();
void findTextSuccessiveShouldCallAllCallbacks();
- void supportedContentType();
- // [Qt] tst_QWebEnginePage::infiniteLoopJS() timeouts with DFG JIT
- // https://bugs.webkit.org/show_bug.cgi?id=79040
- // void infiniteLoopJS();
void deleteQWebEngineViewTwice();
- void renderOnRepaintRequestedShouldNotRecurse();
void loadSignalsOrder_data();
void loadSignalsOrder();
void openWindowDefaultSize();
- void cssMediaTypeGlobalSetting();
- void cssMediaTypePageSetting();
#ifdef Q_OS_MAC
void macCopyUnicodeToClipboard();
@@ -170,7 +142,6 @@ private Q_SLOTS:
// Tests from tst_QWebEngineFrame
- void horizontalScrollAfterBack();
void symmetricUrl();
void progressSignal();
void urlChange();
@@ -182,8 +153,6 @@ private Q_SLOTS:
void setHtmlWithStylesheetResource();
void setHtmlWithBaseURL();
void setHtmlWithJSAlert();
- void inputFieldFocus();
- void hitTestContent();
void baseUrl_data();
void baseUrl();
void scrollPosition();
@@ -191,7 +160,6 @@ private Q_SLOTS:
void evaluateWillCauseRepaint();
void setContent_data();
void setContent();
- void setCacheLoadControlAttribute();
void setUrlWithPendingLoads();
void setUrlToEmpty();
void setUrlToInvalid();
@@ -368,18 +336,6 @@ private:
bool m_allowGeolocation;
};
-// [Qt] tst_QWebEnginePage::infiniteLoopJS() timeouts with DFG JIT
-// https://bugs.webkit.org/show_bug.cgi?id=79040
-/*
-void tst_QWebEnginePage::infiniteLoopJS()
-{
- JSTestPage newPage(m_view);
- m_view->setPage(&newPage);
- m_view->setHtml(QString("<html><body>test</body></html>"), QUrl());
- m_view->page()->evaluateJavaScript("var run = true; var a = 1; while (run) { a++; }");
-}
-*/
-
void tst_QWebEnginePage::geolocationRequestJS_data()
{
QTest::addColumn<bool>("allowed");
@@ -653,170 +609,6 @@ protected:
}
};
-void tst_QWebEnginePage::userStyleSheet()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- TestNetworkManager* networkManager = new TestNetworkManager(m_page);
- m_page->setNetworkAccessManager(networkManager);
-
- m_page->settings()->setUserStyleSheetUrl(QUrl("data:text/css;charset=utf-8;base64,"
- + QByteArray("p { background-image: url('http://does.not/exist.png');}").toBase64()));
- m_view->setHtml("<p>hello world</p>");
- QSignalSpy spyFinished(m_view, &QWebEngineView::loadFinished);
- QVERIFY(spyFinished.wait());
-
- QVERIFY(networkManager->requestedUrls.count() >= 1);
- QCOMPARE(networkManager->requestedUrls.at(0), QUrl("http://does.not/exist.png"));
-#endif
-}
-
-void tst_QWebEnginePage::userStyleSheetFromLocalFileUrl()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- TestNetworkManager* networkManager = new TestNetworkManager(m_page);
- m_page->setNetworkAccessManager(networkManager);
-
- QUrl styleSheetUrl = QUrl::fromLocalFile(TESTS_SOURCE_DIR + QLatin1String("qwebenginepage/resources/user.css"));
- m_page->settings()->setUserStyleSheetUrl(styleSheetUrl);
- m_view->setHtml("<p>hello world</p>");
- QSignalSpy spyFinished(m_view, &QWebEngineView::loadFinished);
- QVERIFY(spyFinished.wait());
-
- QVERIFY(networkManager->requestedUrls.count() >= 1);
- QCOMPARE(networkManager->requestedUrls.at(0), QUrl("http://does.not/exist.png"));
-#endif
-}
-
-void tst_QWebEnginePage::userStyleSheetFromQrcUrl()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- TestNetworkManager* networkManager = new TestNetworkManager(m_page);
- m_page->setNetworkAccessManager(networkManager);
-
- m_page->settings()->setUserStyleSheetUrl(QUrl("qrc:///resources/user.css"));
- m_view->setHtml("<p>hello world</p>");
- QSignalSpy spyFinished(m_view, &QWebEngineView::loadFinished);
- QVERIFY(spyFinished.wait());
-
- QVERIFY(networkManager->requestedUrls.count() >= 1);
- QCOMPARE(networkManager->requestedUrls.at(0), QUrl("http://does.not/exist.png"));
-#endif
-}
-
-void tst_QWebEnginePage::modified()
-{
-#if !defined(QWEBENGINEPAGE_ISMODIFIED)
- QSKIP("QWEBENGINEPAGE_ISMODIFIED");
-#else
- m_page->setUrl(QUrl("data:text/html,<body>blub"));
- QSignalSpy spyFinished(m_view, &QWebEngineView::loadFinished);
- QVERIFY(spyFinished.wait());
-
- m_page->setUrl(QUrl("data:text/html,<body id=foo contenteditable>blah"));
- QSignalSpy spyFinished(m_view, &QWebEngineView::loadFinished);
- QVERIFY(spyFinished.wait());
-
- QVERIFY(!m_page->isModified());
-
- m_page->runJavaScript("document.getElementById('foo').focus()");
- evaluateJavaScriptSync(m_page, "document.execCommand('InsertText', true, 'Test');");
-
- QVERIFY(m_page->isModified());
-
- evaluateJavaScriptSync(m_page, "document.execCommand('Undo', true);");
-
- QVERIFY(!m_page->isModified());
-
- evaluateJavaScriptSync(m_page, "document.execCommand('Redo', true);");
-
- QVERIFY(m_page->isModified());
-
- QVERIFY(m_page->history()->canGoBack());
- QVERIFY(!m_page->history()->canGoForward());
- QCOMPARE(m_page->history()->count(), 2);
- QVERIFY(m_page->history()->backItem().isValid());
- QVERIFY(!m_page->history()->forwardItem().isValid());
-
- m_page->history()->back();
- QSignalSpy spyFinished(m_view, &QWebEngineView::loadFinished);
- QVERIFY(spyFinished.wait());
-
- QVERIFY(!m_page->history()->canGoBack());
- QVERIFY(m_page->history()->canGoForward());
-
- QVERIFY(!m_page->isModified());
-
- QCOMPARE(m_page->history()->currentItemIndex(), 0);
-
- m_page->history()->setMaximumItemCount(3);
- QCOMPARE(m_page->history()->maximumItemCount(), 3);
-
- QVariant variant("string test");
- m_page->history()->currentItem().setUserData(variant);
- QVERIFY(m_page->history()->currentItem().userData().toString() == "string test");
-
- m_page->setUrl(QUrl("data:text/html,<body>This is second page"));
- m_page->setUrl(QUrl("data:text/html,<body>This is third page"));
- QCOMPARE(m_page->history()->count(), 2);
- m_page->setUrl(QUrl("data:text/html,<body>This is fourth page"));
- QCOMPARE(m_page->history()->count(), 2);
- m_page->setUrl(QUrl("data:text/html,<body>This is fifth page"));
- QSignalSpy spy(m_page, &QWebEnginePage::saveFrameStateRequested);
- QVERIFY(spy.wait());
-#endif
-}
-
-// https://bugs.webkit.org/show_bug.cgi?id=51331
-void tst_QWebEnginePage::updatePositionDependentActionsCrash()
-{
-#if !defined(QWEBENGINEPAGE_UPDATEPOSITIONDEPENDENTACTIONS)
- QSKIP("QWEBENGINEPAGE_UPDATEPOSITIONDEPENDENTACTIONS");
-#else
- QWebEngineView view;
- view.setHtml("<p>test");
- QPoint pos(0, 0);
- view.page()->updatePositionDependentActions(pos);
- QMenu* contextMenu = 0;
- const QList<QObject *> children = view.children();
- for (QObject *child : children) {
- contextMenu = qobject_cast<QMenu*>(child);
- if (contextMenu)
- break;
- }
- QVERIFY(!contextMenu);
-#endif
-}
-
-// https://bugs.webkit.org/show_bug.cgi?id=20357
-void tst_QWebEnginePage::contextMenuCrash()
-{
-#if !defined(QWEBENGINEPAGE_SWALLOWCONTEXTMENUEVENT)
- QSKIP("QWEBENGINEPAGE_SWALLOWCONTEXTMENUEVENT");
-#else
- QWebEngineView view;
- view.setHtml("<p>test");
- QPoint pos(0, 0);
- QContextMenuEvent event(QContextMenuEvent::Mouse, pos);
- view.page()->swallowContextMenuEvent(&event);
- view.page()->updatePositionDependentActions(pos);
- QMenu* contextMenu = 0;
- const QList<QObject *> children = view.children();
- for (QObject *child : children) {
- contextMenu = qobject_cast<QMenu*>(child);
- if (contextMenu)
- break;
- }
- QVERIFY(contextMenu);
- delete contextMenu;
-#endif
-}
-
void tst_QWebEnginePage::multipleProfilesAndLocalStorage()
{
QDir dir(tmpDirPath());
@@ -889,204 +681,6 @@ public:
}
};
-void tst_QWebEnginePage::cursorMovements()
-{
-#if !defined(QWEBENGINEPAGE_SELECTEDTEXT)
- QSKIP("QWEBENGINEPAGE_SELECTEDTEXT");
-#else
- QScopedPointer<CursorTrackedPage> page(new CursorTrackedPage);
- QString content("<html><body><p id=one>The quick brown fox</p><p id=two>jumps over the lazy dog</p><p>May the source<br/>be with you!</p></body></html>");
- page->setHtml(content);
-
- // this will select the first paragraph
- QString script = "var range = document.createRange(); " \
- "var node = document.getElementById(\"one\"); " \
- "range.selectNode(node); " \
- "getSelection().addRange(range);";
- evaluateJavaScriptSync(page.data(), script);
- QCOMPARE(page->selectedText().trimmed(), QString::fromLatin1("The quick brown fox"));
-
- QRegExp regExp(" style=\".*\"");
- regExp.setMinimal(true);
- QCOMPARE(page->selectedHtml().trimmed().replace(regExp, ""), QString::fromLatin1("<p id=\"one\">The quick brown fox</p>"));
-
- // these actions must exist
- QVERIFY(page->action(QWebEnginePage::MoveToNextChar) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToPreviousChar) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToNextWord) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToPreviousWord) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToNextLine) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToPreviousLine) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToStartOfLine) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToEndOfLine) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToStartOfBlock) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToEndOfBlock) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToStartOfDocument) != 0);
- QVERIFY(page->action(QWebEnginePage::MoveToEndOfDocument) != 0);
-
- // right now they are disabled because contentEditable is false
- QCOMPARE(page->action(QWebEnginePage::MoveToNextChar)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToPreviousChar)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToNextWord)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToPreviousWord)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToNextLine)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToPreviousLine)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToStartOfLine)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToEndOfLine)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToStartOfBlock)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToEndOfBlock)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToStartOfDocument)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::MoveToEndOfDocument)->isEnabled(), false);
-
- // make it editable before navigating the cursor
- page->setContentEditable(true);
-
- // here the actions are enabled after contentEditable is true
- QCOMPARE(page->action(QWebEnginePage::MoveToNextChar)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToPreviousChar)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToNextWord)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToPreviousWord)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToNextLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToPreviousLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToStartOfLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToEndOfLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToStartOfBlock)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToEndOfBlock)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToStartOfDocument)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::MoveToEndOfDocument)->isEnabled(), true);
-
- // cursor will be before the word "jump"
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 0);
-
- // cursor will be between 'j' and 'u' in the word "jump"
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 1);
-
- // cursor will be between 'u' and 'm' in the word "jump"
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 2);
-
- // cursor will be after the word "jump"
- page->triggerAction(QWebEnginePage::MoveToNextWord);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 5);
-
- // cursor will be after the word "lazy"
- page->triggerAction(QWebEnginePage::MoveToNextWord);
- page->triggerAction(QWebEnginePage::MoveToNextWord);
- page->triggerAction(QWebEnginePage::MoveToNextWord);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 19);
-
- // cursor will be between 'z' and 'y' in "lazy"
- page->triggerAction(QWebEnginePage::MoveToPreviousChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 18);
-
- // cursor will be between 'a' and 'z' in "lazy"
- page->triggerAction(QWebEnginePage::MoveToPreviousChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 17);
-
- // cursor will be before the word "lazy"
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 15);
-
- // cursor will be before the word "quick"
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 4);
-
- // cursor will be between 'p' and 's' in the word "jumps"
- page->triggerAction(QWebEnginePage::MoveToNextWord);
- page->triggerAction(QWebEnginePage::MoveToNextWord);
- page->triggerAction(QWebEnginePage::MoveToNextWord);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 4);
-
- // cursor will be before the word "jumps"
- page->triggerAction(QWebEnginePage::MoveToStartOfLine);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 0);
-
- // cursor will be after the word "dog"
- page->triggerAction(QWebEnginePage::MoveToEndOfLine);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 23);
-
- // cursor will be between 'w' and 'n' in "brown"
- page->triggerAction(QWebEnginePage::MoveToStartOfLine);
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 14);
-
- // cursor will be after the word "fox"
- page->triggerAction(QWebEnginePage::MoveToEndOfLine);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 19);
-
- // cursor will be before the word "The"
- page->triggerAction(QWebEnginePage::MoveToStartOfDocument);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 0);
-
- // cursor will be after the word "you!"
- page->triggerAction(QWebEnginePage::MoveToEndOfDocument);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 12);
-
- // cursor will be before the word "be"
- page->triggerAction(QWebEnginePage::MoveToStartOfBlock);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 0);
-
- // cursor will be after the word "you!"
- page->triggerAction(QWebEnginePage::MoveToEndOfBlock);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 12);
-
- // try to move before the document start
- page->triggerAction(QWebEnginePage::MoveToStartOfDocument);
- page->triggerAction(QWebEnginePage::MoveToPreviousChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 0);
- page->triggerAction(QWebEnginePage::MoveToStartOfDocument);
- page->triggerAction(QWebEnginePage::MoveToPreviousWord);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 0);
-
- // try to move past the document end
- page->triggerAction(QWebEnginePage::MoveToEndOfDocument);
- page->triggerAction(QWebEnginePage::MoveToNextChar);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 12);
- page->triggerAction(QWebEnginePage::MoveToEndOfDocument);
- page->triggerAction(QWebEnginePage::MoveToNextWord);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 12);
-#endif
-}
-
void tst_QWebEnginePage::textSelection()
{
QWebEngineView view;
@@ -1101,35 +695,6 @@ void tst_QWebEnginePage::textSelection()
// these actions must exist
QVERIFY(page->action(QWebEnginePage::SelectAll) != 0);
-#if defined(QWEBENGINEPAGE_SELECTACTIONS)
- QVERIFY(page->action(QWebEnginePage::SelectNextChar) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectPreviousChar) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectNextWord) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectPreviousWord) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectNextLine) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectPreviousLine) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectStartOfLine) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectEndOfLine) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectStartOfBlock) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectEndOfBlock) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectStartOfDocument) != 0);
- QVERIFY(page->action(QWebEnginePage::SelectEndOfDocument) != 0);
-
- // right now they are disabled because contentEditable is false and
- // there isn't an existing selection to modify
- QCOMPARE(page->action(QWebEnginePage::SelectNextChar)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousChar)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectNextWord)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousWord)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectNextLine)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousLine)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfLine)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfLine)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfBlock)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfBlock)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfDocument)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfDocument)->isEnabled(), false);
-#endif
// ..but SelectAll is awalys enabled
QCOMPARE(page->action(QWebEnginePage::SelectAll)->isEnabled(), true);
@@ -1144,173 +709,10 @@ void tst_QWebEnginePage::textSelection()
"getSelection().addRange(range);";
evaluateJavaScriptSync(page, selectScript);
QCOMPARE(page->selectedText().trimmed(), QString::fromLatin1("The quick brown fox"));
-#if defined(QWEBENGINEPAGE_SELECTEDHTML)
- QRegExp regExp(" style=\".*\"");
- regExp.setMinimal(true);
- QCOMPARE(page->selectedHtml().trimmed().replace(regExp, ""), QString::fromLatin1("<p id=\"one\">The quick brown fox</p>"));
-#endif
// Make sure hasSelection returns true, since there is selected text now...
QCOMPARE(page->hasSelection(), true);
-
-#if defined(QWEBENGINEPAGE_SELECTACTIONS)
- // here the actions are enabled after a selection has been created
- QCOMPARE(page->action(QWebEnginePage::SelectNextChar)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousChar)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectNextWord)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousWord)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectNextLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfBlock)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfBlock)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfDocument)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfDocument)->isEnabled(), true);
-
- // make it editable before navigating the cursor
- page->setContentEditable(true);
-
- // cursor will be before the word "The", this makes sure there is a charet
- page->triggerAction(QWebEnginePage::MoveToStartOfDocument);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 0);
-
- // here the actions are enabled after contentEditable is true
- QCOMPARE(page->action(QWebEnginePage::SelectNextChar)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousChar)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectNextWord)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousWord)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectNextLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectPreviousLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfLine)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfBlock)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfBlock)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectStartOfDocument)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SelectEndOfDocument)->isEnabled(), true);
-#endif
}
-void tst_QWebEnginePage::textEditing()
-{
-#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
- QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
-#else
- QScopedPointer<CursorTrackedPage> page(new CursorTrackedPage);
- QString content("<html><body><p id=one>The quick brown fox</p>" \
- "<p id=two>jumps over the lazy dog</p>" \
- "<p>May the source<br/>be with you!</p></body></html>");
- page->setHtml(content);
-
- // these actions must exist
- QVERIFY(page->action(QWebEnginePage::Cut) != 0);
- QVERIFY(page->action(QWebEnginePage::Copy) != 0);
- QVERIFY(page->action(QWebEnginePage::Paste) != 0);
- QVERIFY(page->action(QWebEnginePage::DeleteStartOfWord) != 0);
- QVERIFY(page->action(QWebEnginePage::DeleteEndOfWord) != 0);
- QVERIFY(page->action(QWebEnginePage::SetTextDirectionDefault) != 0);
- QVERIFY(page->action(QWebEnginePage::SetTextDirectionLeftToRight) != 0);
- QVERIFY(page->action(QWebEnginePage::SetTextDirectionRightToLeft) != 0);
- QVERIFY(page->action(QWebEnginePage::ToggleBold) != 0);
- QVERIFY(page->action(QWebEnginePage::ToggleItalic) != 0);
- QVERIFY(page->action(QWebEnginePage::ToggleUnderline) != 0);
- QVERIFY(page->action(QWebEnginePage::InsertParagraphSeparator) != 0);
- QVERIFY(page->action(QWebEnginePage::InsertLineSeparator) != 0);
- QVERIFY(page->action(QWebEnginePage::PasteAndMatchStyle) != 0);
- QVERIFY(page->action(QWebEnginePage::RemoveFormat) != 0);
- QVERIFY(page->action(QWebEnginePage::ToggleStrikethrough) != 0);
- QVERIFY(page->action(QWebEnginePage::ToggleSubscript) != 0);
- QVERIFY(page->action(QWebEnginePage::ToggleSuperscript) != 0);
- QVERIFY(page->action(QWebEnginePage::InsertUnorderedList) != 0);
- QVERIFY(page->action(QWebEnginePage::InsertOrderedList) != 0);
- QVERIFY(page->action(QWebEnginePage::Indent) != 0);
- QVERIFY(page->action(QWebEnginePage::Outdent) != 0);
- QVERIFY(page->action(QWebEnginePage::AlignCenter) != 0);
- QVERIFY(page->action(QWebEnginePage::AlignJustified) != 0);
- QVERIFY(page->action(QWebEnginePage::AlignLeft) != 0);
- QVERIFY(page->action(QWebEnginePage::AlignRight) != 0);
-
- // right now they are disabled because contentEditable is false
- QCOMPARE(page->action(QWebEnginePage::Cut)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::Paste)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::DeleteStartOfWord)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::DeleteEndOfWord)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SetTextDirectionDefault)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SetTextDirectionLeftToRight)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::SetTextDirectionRightToLeft)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::ToggleBold)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::ToggleItalic)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::ToggleUnderline)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::InsertParagraphSeparator)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::InsertLineSeparator)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::PasteAndMatchStyle)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::RemoveFormat)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::ToggleStrikethrough)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::ToggleSubscript)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::ToggleSuperscript)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::InsertUnorderedList)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::InsertOrderedList)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::Indent)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::Outdent)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::AlignCenter)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::AlignJustified)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::AlignLeft)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::AlignRight)->isEnabled(), false);
-
- // Select everything
- page->triggerAction(QWebEnginePage::SelectAll);
-
- // make sure it is enabled since there is a selection
- QCOMPARE(page->action(QWebEnginePage::Copy)->isEnabled(), true);
-
- // make it editable before navigating the cursor
- page->setContentEditable(true);
-
- // clear the selection
- page->triggerAction(QWebEnginePage::MoveToStartOfDocument);
- QVERIFY(page->isSelectionCollapsed());
- QCOMPARE(page->selectionStartOffset(), 0);
-
- // make sure it is disabled since there isn't a selection
- QCOMPARE(page->action(QWebEnginePage::Copy)->isEnabled(), false);
-
- // here the actions are enabled after contentEditable is true
- QCOMPARE(page->action(QWebEnginePage::Paste)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::DeleteStartOfWord)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::DeleteEndOfWord)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SetTextDirectionDefault)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SetTextDirectionLeftToRight)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::SetTextDirectionRightToLeft)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::ToggleBold)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::ToggleItalic)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::ToggleUnderline)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::InsertParagraphSeparator)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::InsertLineSeparator)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::PasteAndMatchStyle)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::ToggleStrikethrough)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::ToggleSubscript)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::ToggleSuperscript)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::InsertUnorderedList)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::InsertOrderedList)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::Indent)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::Outdent)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::AlignCenter)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::AlignJustified)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::AlignLeft)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::AlignRight)->isEnabled(), true);
-
- // make sure these are disabled since there isn't a selection
- QCOMPARE(page->action(QWebEnginePage::Cut)->isEnabled(), false);
- QCOMPARE(page->action(QWebEnginePage::RemoveFormat)->isEnabled(), false);
-
- // make sure everything is selected
- page->triggerAction(QWebEnginePage::SelectAll);
-
- // this is only true if there is an editable selection
- QCOMPARE(page->action(QWebEnginePage::Cut)->isEnabled(), true);
- QCOMPARE(page->action(QWebEnginePage::RemoveFormat)->isEnabled(), true);
-#endif
-}
void tst_QWebEnginePage::backActionUpdate()
{
@@ -1331,243 +733,39 @@ void tst_QWebEnginePage::backActionUpdate()
QVERIFY(action->isEnabled());
}
-#if defined(QWEBENGINEPAGE_SETTINGS)
-static inline bool testFlag(QWebEnginePage& webPage, QWebEngineSettings::WebAttribute settingAttribute, const QString& jsObjectName, bool settingValue)
-{
- webPage.settings()->setAttribute(settingAttribute, settingValue);
- return evaluateJavaScriptSync(&webPage, QString("(window.%1 != undefined)").arg(jsObjectName)).toBool();
-}
-#endif
-
-void tst_QWebEnginePage::testOptionalJSObjects()
-{
-#if !defined(QWEBENGINESETTINGS)
- QSKIP("QWEBENGINSETTINGS");
-#else
- // Once a feature is enabled and the JS object is accessed turning off the setting will not turn off
- // the visibility of the JS object any more. For this reason this test uses two QWebEnginePage instances.
- // Part of the test is to make sure that the QWebEnginePage instances do not interfere with each other so turning on
- // a feature for one instance will not turn it on for another.
-
- QWebEnginePage webPage1;
- QWebEnginePage webPage2;
-
- webPage1.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("http://www.example.com/"));
- webPage2.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("http://www.example.com/"));
-
- QEXPECT_FAIL("","Feature enabled/disabled checking problem. Look at bugs.webkit.org/show_bug.cgi?id=29867", Continue);
- QCOMPARE(testFlag(webPage1, QWebEngineSettings::OfflineWebApplicationCacheEnabled, "applicationCache", false), false);
- QCOMPARE(testFlag(webPage2, QWebEngineSettings::OfflineWebApplicationCacheEnabled, "applicationCache", true), true);
- QEXPECT_FAIL("","Feature enabled/disabled checking problem. Look at bugs.webkit.org/show_bug.cgi?id=29867", Continue);
- QCOMPARE(testFlag(webPage1, QWebEngineSettings::OfflineWebApplicationCacheEnabled, "applicationCache", false), false);
- QCOMPARE(testFlag(webPage2, QWebEngineSettings::OfflineWebApplicationCacheEnabled, "applicationCache", false), true);
-
- QCOMPARE(testFlag(webPage1, QWebEngineSettings::LocalStorageEnabled, "localStorage", false), false);
- QCOMPARE(testFlag(webPage2, QWebEngineSettings::LocalStorageEnabled, "localStorage", true), true);
- QCOMPARE(testFlag(webPage1, QWebEngineSettings::LocalStorageEnabled, "localStorage", false), false);
- QCOMPARE(testFlag(webPage2, QWebEngineSettings::LocalStorageEnabled, "localStorage", false), true);
-#endif
-}
-
-#if defined(QWEBENGINEPAGE_SETTINGS)
-static inline bool checkLocalStorageVisibility(QWebEnginePage& webPage, bool localStorageEnabled)
-{
- webPage.settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, localStorageEnabled);
- return evaluateJavaScriptSync(&webPage, QString("(window.localStorage != undefined)")).toBool();
-}
-#endif
-
-void tst_QWebEnginePage::testLocalStorageVisibility()
-{
-#if !defined(QWEBENGINEPAGE_SETTINGS)
- QSKIP("QWEBENGINEPAGE_SETTINGS");
-#else
- // Local storage's visibility depends on its security origin, which depends on base url.
- // Initially, it will test it with base urls that get a globally unique origin, which may not
- // be able to use local storage even if the feature is enabled. Then later the same test is
- // done but with urls that would get a valid origin, so local storage could be used.
- // Before every test case it checks if local storage is not already visible.
-
- QWebEnginePage webPage;
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl());
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), false);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("invalid"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), false);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("://misparsed.com"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), false);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("http://"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), false);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("about:blank"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), false);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("data:text/html,test"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), false);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("file:///"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), true);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("http://www.example.com"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), true);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("https://www.example.com"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), true);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("ftp://files.example.com"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), true);
-
- webPage.currentFrame()->setHtml(QString("<html><body>test</body></html>"), QUrl("file:///path/to/index.html"));
-
- QCOMPARE(checkLocalStorageVisibility(webPage, false), false);
- QCOMPARE(checkLocalStorageVisibility(webPage, true), true);
-#endif
-}
-
-void tst_QWebEnginePage::testEnablePersistentStorage()
-{
-#if !defined(QWEBENGINESETTINGS)
- QSKIP("QWEBENGINESETTINGS");
-#else
- QWebEnginePage webPage;
-
- // By default all persistent options should be disabled
- QCOMPARE(webPage.settings()->testAttribute(QWebEngineSettings::LocalStorageEnabled), false);
- QCOMPARE(webPage.settings()->testAttribute(QWebEngineSettings::OfflineStorageDatabaseEnabled), false);
- QCOMPARE(webPage.settings()->testAttribute(QWebEngineSettings::OfflineWebApplicationCacheEnabled), false);
- QVERIFY(webPage.settings()->iconDatabasePath().isEmpty());
-
- QWebEngineSettings::enablePersistentStorage();
-
-
- QTRY_COMPARE(webPage.settings()->testAttribute(QWebEngineSettings::LocalStorageEnabled), true);
- QTRY_COMPARE(webPage.settings()->testAttribute(QWebEngineSettings::OfflineStorageDatabaseEnabled), true);
- QTRY_COMPARE(webPage.settings()->testAttribute(QWebEngineSettings::OfflineWebApplicationCacheEnabled), true);
-
- QTRY_VERIFY(!webPage.settings()->offlineStoragePath().isEmpty());
- QTRY_VERIFY(!webPage.settings()->offlineWebApplicationCachePath().isEmpty());
- QTRY_VERIFY(!webPage.settings()->iconDatabasePath().isEmpty());
-#endif
-}
-
-
-#if defined(QWEBENGINEPAGE_ERRORPAGEEXTENSION)
-class ErrorPage : public QWebEnginePage
-{
-public:
-
- ErrorPage(QWidget* parent = 0): QWebEnginePage(parent)
- {
- }
-
- virtual bool supportsExtension(Extension extension) const
- {
- return extension == ErrorPageExtension;
- }
-
- virtual bool extension(Extension, const ExtensionOption* option, ExtensionReturn* output)
- {
- ErrorPageExtensionReturn* errorPage = static_cast<ErrorPageExtensionReturn*>(output);
-
- errorPage->contentType = "text/html";
- errorPage->content = "error";
- return true;
- }
-};
-#endif
-
-void tst_QWebEnginePage::errorPageExtension()
-{
-#if !defined(QWEBENGINEPAGE_ERRORPAGEEXTENSION)
- QSKIP("QWEBENGINEPAGE_ERRORPAGEEXTENSION");
-#else
- ErrorPage page;
- m_view->setPage(&page);
-
- QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool)));
-
- m_view->setUrl(QUrl("data:text/html,foo"));
- QTRY_COMPARE(spyLoadFinished.count(), 1);
-
- page.setUrl(QUrl("http://non.existent/url"));
- QTRY_COMPARE(spyLoadFinished.count(), 2);
- QCOMPARE(toPlainTextSync(&page), QString("error"));
- QCOMPARE(page.history()->count(), 2);
- QCOMPARE(page.history()->currentItem().url(), QUrl("http://non.existent/url"));
- QCOMPARE(page.history()->canGoBack(), true);
- QCOMPARE(page.history()->canGoForward(), false);
-
- page.triggerAction(QWebEnginePage::Back);
- QTRY_COMPARE(page.history()->canGoBack(), false);
- QTRY_COMPARE(page.history()->canGoForward(), true);
-
- page.triggerAction(QWebEnginePage::Forward);
- QTRY_COMPARE(page.history()->canGoBack(), true);
- QTRY_COMPARE(page.history()->canGoForward(), false);
-
- page.triggerAction(QWebEnginePage::Back);
- QTRY_COMPARE(page.history()->canGoBack(), false);
- QTRY_COMPARE(page.history()->canGoForward(), true);
- QTRY_COMPARE(page.history()->currentItem().url(), QUrl("data:text/html,foo"));
-
- m_view->setPage(0);
-#endif
-}
-
-void tst_QWebEnginePage::errorPageExtensionLoadFinished()
+void tst_QWebEnginePage::localStorageVisibility()
{
-#if !defined(QWEBENGINEPAGE_ERRORPAGEEXTENSION)
- QSKIP("QWEBENGINEPAGE_ERRORPAGEEXTENSION");
-#else
- ErrorPage page;
- m_view->setPage(&page);
-
- QSignalSpy spyLoadFinished(m_view, SIGNAL(loadFinished(bool)));
- QSignalSpy spyFrameLoadFinished(m_view->page(), SIGNAL(loadFinished(bool)));
-
- m_view->setUrl(QUrl("data:text/html,foo"));
- QTRY_COMPARE(spyLoadFinished.count(), 1);
- QTRY_COMPARE(spyFrameLoadFinished.count(), 1);
-
- const bool loadSucceded = spyLoadFinished.at(0).at(0).toBool();
- QVERIFY(loadSucceded);
- const bool frameLoadSucceded = spyFrameLoadFinished.at(0).at(0).toBool();
- QVERIFY(frameLoadSucceded);
-
- m_view->page()->setUrl(QUrl("http://non.existent/url"));
- QTRY_COMPARE(spyLoadFinished.count(), 2);
- QTRY_COMPARE(spyFrameLoadFinished.count(), 2);
-
- const bool nonExistantLoadSucceded = spyLoadFinished.at(1).at(0).toBool();
- QVERIFY(nonExistantLoadSucceded);
- const bool nonExistantFrameLoadSucceded = spyFrameLoadFinished.at(1).at(0).toBool();
- QVERIFY(nonExistantFrameLoadSucceded);
-
- m_view->setPage(0);
-#endif
+ QWebEngineProfile profile;
+ QWebEnginePage webPage1(&profile);
+ QWebEnginePage webPage2(&profile);
+
+ webPage1.settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
+ webPage2.settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
+
+ QSignalSpy loadSpy1(&webPage1, &QWebEnginePage::loadFinished);
+ QSignalSpy loadSpy2(&webPage2, &QWebEnginePage::loadFinished);
+ webPage1.setHtml(QString("<html><body>test</body></html>"), QUrl("http://www.example.com/"));
+ webPage2.setHtml(QString("<html><body>test</body></html>"), QUrl("http://www.example.com/"));
+ QTRY_COMPARE(loadSpy1.count(), 1);
+ QTRY_COMPARE(loadSpy2.count(), 1);
+
+ // The attribute determines the visibility of the window.localStorage object.
+ QVERIFY(evaluateJavaScriptSync(&webPage1, QString("(window.localStorage != undefined)")).toBool());
+ QVERIFY(!evaluateJavaScriptSync(&webPage2, QString("(window.localStorage != undefined)")).toBool());
+
+ // Switching the feature off does not actively remove the object from webPage1.
+ webPage1.settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, false);
+ webPage2.settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
+ QVERIFY(evaluateJavaScriptSync(&webPage1, QString("(window.localStorage != undefined)")).toBool());
+ QVERIFY(evaluateJavaScriptSync(&webPage2, QString("(window.localStorage != undefined)")).toBool());
+
+ // The object disappears only after reloading.
+ webPage1.triggerAction(QWebEnginePage::Reload);
+ webPage2.triggerAction(QWebEnginePage::Reload);
+ QTRY_COMPARE(loadSpy1.count(), 2);
+ QTRY_COMPARE(loadSpy2.count(), 2);
+ QVERIFY(!evaluateJavaScriptSync(&webPage1, QString("(window.localStorage != undefined)")).toBool());
+ QVERIFY(evaluateJavaScriptSync(&webPage2, QString("(window.localStorage != undefined)")).toBool());
}
void tst_QWebEnginePage::userAgentNewlineStripping()
@@ -1592,70 +790,9 @@ void tst_QWebEnginePage::crashTests_LazyInitializationOfMainFrame()
webPage.selectedText();
}
{
-#if defined(QWEBENGINEPAGE_SELECTEDHTML)
- QWebEnginePage webPage;
- webPage.selectedHtml();
-#endif
- }
- {
QWebEnginePage webPage;
webPage.triggerAction(QWebEnginePage::Back, true);
}
- {
-#if defined(QWEBENGINEPAGE_UPDATEPOSITIONDEPENDENTACTIONS)
- QWebEnginePage webPage;
- QPoint pos(10,10);
- webPage.updatePositionDependentActions(pos);
-#endif
- }
-}
-
-#if defined(QWEBENGINEPAGE_RENDER)
-static void takeScreenshot(QWebEnginePage* page)
-{
- page->setViewportSize(page->contentsSize());
- QImage image(page->viewportSize(), QImage::Format_ARGB32);
- QPainter painter(&image);
- page->render(&painter);
- painter.end();
-}
-#endif
-
-void tst_QWebEnginePage::screenshot_data()
-{
- QTest::addColumn<QString>("html");
- QTest::newRow("WithoutPlugin") << "<html><body id='b'>text</body></html>";
- QTest::newRow("WindowedPlugin") << QString("<html><body id='b'>text<embed src='resources/test.swf'></embed></body></html>");
- QTest::newRow("WindowlessPlugin") << QString("<html><body id='b'>text<embed src='resources/test.swf' wmode='transparent'></embed></body></html>");
-}
-
-void tst_QWebEnginePage::screenshot()
-{
-#if !defined(QWEBENGINESETTINGS)
- QSKIP("QWEBENGINESETTINGS");
-#else
- if (!QDir(TESTS_SOURCE_DIR).exists())
- W_QSKIP(QString("This test requires access to resources found in '%1'").arg(TESTS_SOURCE_DIR).toLatin1().constData(), SkipAll);
-
- QDir::setCurrent(TESTS_SOURCE_DIR);
-
- QFETCH(QString, html);
- QWebEnginePage page;
- page.settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
- page.setHtml(html, QUrl::fromLocalFile(TESTS_SOURCE_DIR));
- QVERIFY(spyFinished.wait(2000));
-
- // take screenshot without a view
- takeScreenshot(&page);
-
- QWebEngineView view;
- view.setPage(&page);
-
- // take screenshot when attached to a view
- takeScreenshot(&page);
-
- QDir::setCurrent(QApplication::applicationDirPath());
-#endif
}
#if defined(ENABLE_WEBGL) && ENABLE_WEBGL
@@ -1754,37 +891,6 @@ void tst_QWebEnginePage::testJSPrompt()
QVERIFY(res);
}
-void tst_QWebEnginePage::testStopScheduledPageRefresh()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- // Without QWebEnginePage::StopScheduledPageRefresh
- QWebEnginePage page1;
- page1.setNetworkAccessManager(new TestNetworkManager(&page1));
- page1.setHtml("<html><head>"
- "<meta http-equiv=\"refresh\"content=\"0;URL=qrc:///resources/index.html\">"
- "</head><body><h1>Page redirects immediately...</h1>"
- "</body></html>");
- QSignalSpy spyFinished(&page1, &QWebEnginePage::loadFinished);
- QVERIFY(spyFinished.wait();
- QTest::qWait(500);
- QCOMPARE(page1.url(), QUrl(QLatin1String("qrc:///resources/index.html")));
-
- // With QWebEnginePage::StopScheduledPageRefresh
- QWebEnginePage page2;
- page2.setNetworkAccessManager(new TestNetworkManager(&page2));
- page2.setHtml("<html><head>"
- "<meta http-equiv=\"refresh\"content=\"1;URL=qrc:///resources/index.html\">"
- "</head><body><h1>Page redirect test with 1 sec timeout...</h1>"
- "</body></html>");
- page2.triggerAction(QWebEnginePage::StopScheduledPageRefresh);
- QTest::qWait(1500);
- QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118673", Continue);
- QCOMPARE(page2.url().toString(), QLatin1String("about:blank"));
-#endif
-}
-
void tst_QWebEnginePage::findText()
{
QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool)));
@@ -1884,95 +990,6 @@ void tst_QWebEnginePage::findTextSuccessiveShouldCallAllCallbacks()
QVERIFY(spy5.wasCalled());
}
-#if defined(QWEBENGINEPAGE_SUPPORTEDCONTENTTYPES)
-static QString getMimeTypeForExtension(const QString &ext)
-{
- QMimeType mimeType = QMimeDatabase().mimeTypeForFile(QStringLiteral("filename.") + ext.toLower(), QMimeDatabase::MatchExtension);
- if (mimeType.isValid() && !mimeType.isDefault())
- return mimeType.name();
-
- return QString();
-}
-#endif
-
-void tst_QWebEnginePage::supportedContentType()
-{
-#if !defined(QWEBENGINEPAGE_SUPPORTEDCONTENTTYPES)
- QSKIP("QWEBENGINEPAGE_SUPPORTEDCONTENTTYPES");
-#else
- QStringList contentTypes;
-
- // Add supported non image types...
- contentTypes << "text/html" << "text/xml" << "text/xsl" << "text/plain" << "text/"
- << "application/xml" << "application/xhtml+xml" << "application/vnd.wap.xhtml+xml"
- << "application/rss+xml" << "application/atom+xml" << "application/json";
-
-#if ENABLE_MHTML
- contentTypes << "application/x-mimearchive";
-#endif
-
- // Add supported image types...
- const QList<QByteArray> supportedImageFormats = QImageWriter::supportedImageFormats();
- for (const QByteArray &imageType : supportedImageFormats) {
- const QString mimeType = getMimeTypeForExtension(imageType);
- if (!mimeType.isEmpty())
- contentTypes << mimeType;
- }
-
- // Get the mime types supported by webengine...
- const QStringList supportedContentTypes = m_page->supportedContentTypes();
-
- for (const QString &mimeType : qAsConst(contentTypes))
- QVERIFY2(supportedContentTypes.contains(mimeType), QString("'%1' is not a supported content type!").arg(mimeType).toLatin1());
-
- for (const QString &mimeType : qAsConst(contentTypes))
- QVERIFY2(m_page->supportsContentType(mimeType), QString("Cannot handle content types '%1'!").arg(mimeType).toLatin1());
-#endif
-}
-
-void tst_QWebEnginePage::thirdPartyCookiePolicy()
-{
-#if !defined(DUMPRENDERTREESUPPORTQT)
- QSKIP("DUMPRENDERTREESUPPORTQT");
-#else
- QWebEngineSettings::globalSettings()->setThirdPartyCookiePolicy(QWebEngineSettings::AlwaysBlockThirdPartyCookies);
- m_page->networkAccessManager()->setCookieJar(new QNetworkCookieJar());
- QVERIFY(m_page->networkAccessManager()->cookieJar());
-
- // These are all first-party cookies, so should pass.
- QVERIFY(DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://www.example.com"), QUrl("http://example.com")));
- QVERIFY(DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://www.example.com"), QUrl("http://doc.example.com")));
- QVERIFY(DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://aaa.www.example.com"), QUrl("http://doc.example.com")));
- QVERIFY(DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://example.com"), QUrl("http://www.example.com")));
- QVERIFY(DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://www.example.co.uk"), QUrl("http://example.co.uk")));
- QVERIFY(DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://www.example.co.uk"), QUrl("http://doc.example.co.uk")));
- QVERIFY(DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://aaa.www.example.co.uk"), QUrl("http://doc.example.co.uk")));
- QVERIFY(DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://example.co.uk"), QUrl("http://www.example.co.uk")));
-
- // These are all third-party cookies, so should fail.
- QVERIFY(!DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://www.example.com"), QUrl("http://slashdot.org")));
- QVERIFY(!DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://example.com"), QUrl("http://anotherexample.com")));
- QVERIFY(!DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://anotherexample.com"), QUrl("http://example.com")));
- QVERIFY(!DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://www.example.co.uk"), QUrl("http://slashdot.co.uk")));
- QVERIFY(!DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://example.co.uk"), QUrl("http://anotherexample.co.uk")));
- QVERIFY(!DumpRenderTreeSupportQt::thirdPartyCookiePolicyAllows(m_page->handle(),
- QUrl("http://anotherexample.co.uk"), QUrl("http://example.co.uk")));
-#endif
-}
-
static QWindow *findNewTopLevelWindow(const QWindowList &oldTopLevelWindows)
{
const auto tlws = QGuiApplication::topLevelWindows();
@@ -2078,66 +1095,6 @@ void tst_QWebEnginePage::macCopyUnicodeToClipboard()
}
#endif
-void tst_QWebEnginePage::contextMenuCopy()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- QWebEngineView view;
-
- view.setHtml("<a href=\"http://www.google.com\">You cant miss this</a>");
-
- view.page()->triggerAction(QWebEnginePage::SelectAll);
- QVERIFY(!view.page()->selectedText().isEmpty());
-
- QWebEngineElement link = view.page()->mainFrame()->findFirstElement("a");
- QPoint pos(link.geometry().center());
- QContextMenuEvent event(QContextMenuEvent::Mouse, pos);
- view.page()->swallowContextMenuEvent(&event);
- view.page()->updatePositionDependentActions(pos);
-
- QList<QMenu*> contextMenus = view.findChildren<QMenu*>();
- QVERIFY(!contextMenus.isEmpty());
- QMenu* contextMenu = contextMenus.first();
- QVERIFY(contextMenu);
-
- QList<QAction *> list = contextMenu->actions();
- int index = list.indexOf(view.page()->action(QWebEnginePage::Copy));
- QVERIFY(index != -1);
-#endif
-}
-
-// https://bugs.webkit.org/show_bug.cgi?id=62139
-void tst_QWebEnginePage::contextMenuPopulatedOnce()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- QWebEngineView view;
-
- view.setHtml("<input type=\"text\">");
-
- QWebEngineElement link = view.page()->mainFrame()->findFirstElement("input");
- QPoint pos(link.geometry().center());
- QContextMenuEvent event(QContextMenuEvent::Mouse, pos);
- view.page()->swallowContextMenuEvent(&event);
- view.page()->updatePositionDependentActions(pos);
-
- QList<QMenu*> contextMenus = view.findChildren<QMenu*>();
- QVERIFY(!contextMenus.isEmpty());
- QMenu* contextMenu = contextMenus.first();
- QVERIFY(contextMenu);
-
- QList<QAction *> list = contextMenu->actions();
- QStringList entries;
- while (!list.isEmpty()) {
- QString entry = list.takeFirst()->text();
- QVERIFY(!entries.contains(entry));
- entries << entry;
- }
-#endif
-}
-
void tst_QWebEnginePage::deleteQWebEngineViewTwice()
{
for (int i = 0; i < 2; ++i) {
@@ -2151,62 +1108,6 @@ void tst_QWebEnginePage::deleteQWebEngineViewTwice()
}
}
-#if defined(QWEBENGINEPAGE_RENDER)
-class RepaintRequestedRenderer : public QObject {
- Q_OBJECT
-public:
- RepaintRequestedRenderer(QWebEnginePage* page, QPainter* painter)
- : m_page(page)
- , m_painter(painter)
- , m_recursionCount(0)
- {
- connect(m_page, SIGNAL(repaintRequested(QRect)), this, SLOT(onRepaintRequested(QRect)));
- }
-
-Q_SIGNALS:
- void finished();
-
-private Q_SLOTS:
- void onRepaintRequested(const QRect& rect)
- {
- QCOMPARE(m_recursionCount, 0);
-
- m_recursionCount++;
- m_page->render(m_painter, rect);
- m_recursionCount--;
-
- QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
- }
-
-private:
- QWebEnginePage* m_page;
- QPainter* m_painter;
- int m_recursionCount;
-};
-#endif
-
-void tst_QWebEnginePage::renderOnRepaintRequestedShouldNotRecurse()
-{
-#if !defined(QWEBENGINEPAGE_RENDER)
- QSKIP("QWEBENGINEPAGE_RENDER");
-#else
- QSize viewportSize(720, 576);
- QWebEnginePage page;
-
- QImage image(viewportSize, QImage::Format_ARGB32);
- QPainter painter(&image);
-
- page.setPreferredContentsSize(viewportSize);
- page.setViewportSize(viewportSize);
- RepaintRequestedRenderer r(&page, &painter);
-
- page.setHtml("zalan loves trunk", QUrl());
-
- QSignalSpy spyFinished(&r, &RepaintRequestedRenderer::finished);
- QVERIFY(spyFinished.wait());
-#endif
-}
-
class SpyForLoadSignalsOrder : public QStateMachine {
Q_OBJECT
public:
@@ -2265,24 +1166,6 @@ void tst_QWebEnginePage::loadSignalsOrder()
QTRY_VERIFY(loadSpy.isFinished());
}
-void tst_QWebEnginePage::undoActionHaveCustomText()
-{
-#if !defined(QWEBENGINEPAGE_UNDOACTION)
- QSKIP("QWEBENGINEPAGE_UNDOACTION");
-#else
- m_page->setHtml("<div id=test contenteditable></div>");
- evaluateJavaScriptSync(m_page, "document.getElementById('test').focus()");
-
- evaluateJavaScriptSync(m_page, "document.execCommand('insertText', true, 'Test');");
- QString typingActionText = m_page->action(QWebEnginePage::Undo)->text();
-
- evaluateJavaScriptSync(m_page, "document.execCommand('indent', true);");
- QString alignActionText = m_page->action(QWebEnginePage::Undo)->text();
-
- QVERIFY(typingActionText != alignActionText);
-#endif
-}
-
void tst_QWebEnginePage::renderWidgetHostViewNotShowTopLevel()
{
QWebEnginePage page;
@@ -2601,68 +1484,6 @@ void tst_QWebEnginePage::openWindowDefaultSize()
QCOMPARE(requestedGeometry.height(), 100);
}
-void tst_QWebEnginePage::cssMediaTypeGlobalSetting()
-{
-#if !defined(QWEBENGINESETTINGS_SETCSSMEDIATYPE)
- QSKIP("QWEBENGINESETTINGS_SETCSSMEDIATYPE");
-#else
- QString testHtml("<style>@media tv {body{background-color:red;}}@media handheld {body{background-color:green;}}@media screen {body{background-color:blue;}}</style>");
- QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool)));
-
- QWebEngineSettings::globalSettings()->setCSSMediaType("tv");
- // Clear page specific setting to read from global setting
- m_view->page()->settings()->setCSSMediaType(QString());
- m_view->setHtml(testHtml);
- QTRY_COMPARE(loadSpy.count(), 1);
- QVERIFY(evaluateJavaScriptSync(m_view->page(), "window.matchMedia('tv').matches == true").toBool());
- QVERIFY(QWebEngineSettings::globalSettings()->cssMediaType() == "tv");
-
- QWebEngineSettings::globalSettings()->setCSSMediaType("handheld");
- // Clear page specific setting to read from global setting
- m_view->page()->settings()->setCSSMediaType(QString());
- m_view->setHtml(testHtml);
- QTRY_COMPARE(loadSpy.count(), 2);
- QVERIFY(evaluateJavaScriptSync(m_view->page(), "window.matchMedia('handheld').matches == true").toBool());
- QVERIFY(QWebEngineSettings::globalSettings()->cssMediaType() == "handheld");
-
- QWebEngineSettings::globalSettings()->setCSSMediaType("screen");
- // Clear page specific setting to read from global setting
- m_view->page()->settings()->setCSSMediaType(QString());
- m_view->setHtml(testHtml);
- QTRY_COMPARE(loadSpy.count(), 3);
- QVERIFY(evaluateJavaScriptSync(m_view->page(), "window.matchMedia('screen').matches == true").toBool());
- QVERIFY(QWebEngineSettings::globalSettings()->cssMediaType() == "screen");
-#endif
-}
-
-void tst_QWebEnginePage::cssMediaTypePageSetting()
-{
-#if !defined(QWEBENGINESETTINGS_SETCSSMEDIATYPE)
- QSKIP("QWEBENGINESETTINGS_SETCSSMEDIATYPE");
-#else
- QString testHtml("<style>@media tv {body{background-color:red;}}@media handheld {body{background-color:green;}}@media screen {body{background-color:blue;}}</style>");
- QSignalSpy loadSpy(m_view, SIGNAL(loadFinished(bool)));
-
- m_view->page()->settings()->setCSSMediaType("tv");
- m_view->setHtml(testHtml);
- QTRY_COMPARE(loadSpy.count(), 1);
- QVERIFY(evaluateJavaScriptSync(m_view->page(), "window.matchMedia('tv').matches == true").toBool());
- QVERIFY(m_view->page()->settings()->cssMediaType() == "tv");
-
- m_view->page()->settings()->setCSSMediaType("handheld");
- m_view->setHtml(testHtml);
- QTRY_COMPARE(loadSpy.count(), 2);
- QVERIFY(evaluateJavaScriptSync(m_view->page(), "window.matchMedia('handheld').matches == true").toBool());
- QVERIFY(m_view->page()->settings()->cssMediaType() == "handheld");
-
- m_view->page()->settings()->setCSSMediaType("screen");
- m_view->setHtml(testHtml);
- QTRY_COMPARE(loadSpy.count(), 3);
- QVERIFY(evaluateJavaScriptSync(m_view->page(), "window.matchMedia('screen').matches == true").toBool());
- QVERIFY(m_view->page()->settings()->cssMediaType() == "screen");
-#endif
-}
-
class JavaScriptCallbackBase
{
public:
@@ -3244,55 +2065,6 @@ void tst_QWebEnginePage::setHtmlWithJSAlert()
QCOMPARE(toHtmlSync(&page), html);
}
-void tst_QWebEnginePage::inputFieldFocus()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- QWebEngineView view;
- view.setHtml("<html><body><input type=\"text\"></input></body></html>");
- view.resize(400, 100);
- view.show();
- QTest::qWaitForWindowExposed(&view);
- view.activateWindow();
- view.setFocus();
- QTRY_VERIFY(view.hasFocus());
-
- // double the flashing time, should at least blink once already
- int delay = qApp->cursorFlashTime() * 2;
-
- // focus the lineedit and check if it blinks
- bool autoSipEnabled = qApp->autoSipEnabled();
- qApp->setAutoSipEnabled(false);
- const QWebEngineElement inputElement = view.page()->documentElement().findFirst(QLatin1String("input[type=text]"));
- QTest::mouseClick(&view, Qt::LeftButton, 0, inputElement.geometry().center());
- m_inputFieldsTestView = &view;
- view.installEventFilter( this );
- QTest::qWait(delay);
- QVERIFY2(m_inputFieldTestPaintCount >= 3,
- "The input field should have a blinking caret");
- qApp->setAutoSipEnabled(autoSipEnabled);
-#endif
-}
-
-void tst_QWebEnginePage::hitTestContent()
-{
-#if !defined(QWEBENGINEELEMENT)
- QSKIP("QWEBENGINEELEMENT");
-#else
- QString html("<html><body><p>A paragraph</p><br/><br/><br/><a href=\"about:blank\" target=\"_foo\" id=\"link\">link text</a></body></html>");
-
- QWebEnginePage page;
- page.setHtml(html);
- page.setViewportSize(QSize(200, 0)); //no height so link is not visible
- const QWebEngineElement linkElement = page.documentElement().findFirst(QLatin1String("a#link"));
- QWebEngineHitTestResult result = page.hitTestContent(linkElement.geometry().center());
- QCOMPARE(result.linkText(), QString("link text"));
- QWebEngineElement link = result.linkElement();
- QCOMPARE(link.attribute("target"), QString("_foo"));
-#endif
-}
-
void tst_QWebEnginePage::baseUrl_data()
{
QTest::addColumn<QString>("html");
@@ -3373,32 +2145,6 @@ void tst_QWebEnginePage::scrollbarsOff()
QVERIFY(evaluateJavaScriptSync(view.page(), "innerWidth == document.documentElement.offsetWidth").toBool());
}
-void tst_QWebEnginePage::horizontalScrollAfterBack()
-{
-#if !defined(QWEBENGINESETTINGS)
- QSKIP("QWEBENGINESETTINGS");
-#else
- QWebEngineView view;
- QSignalSpy loadSpy(view.page(), SIGNAL(loadFinished(bool)));
-
- view.page()->settings()->setMaximumPagesInCache(2);
- view.page()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAsNeeded);
- view.page()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAsNeeded);
-
- view.load(QUrl("qrc:/resources/testiframe2.html"));
- view.resize(200, 200);
- QTRY_COMPARE(loadSpy.count(), 1);
- QTRY_VERIFY((view.page()->scrollBarGeometry(Qt::Horizontal)).height());
-
- view.load(QUrl("qrc:/resources/testiframe.html"));
- QTRY_COMPARE(loadSpy.count(), 2);
-
- view.page()->triggerAction(QWebEnginePage::Back);
- QTRY_COMPARE(loadSpy.count(), 3);
- QTRY_VERIFY((view.page()->scrollBarGeometry(Qt::Horizontal)).height());
-#endif
-}
-
class WebView : public QWebEngineView
{
Q_OBJECT
@@ -3493,35 +2239,6 @@ private:
QNetworkRequest::CacheLoadControl m_lastCacheLoad;
};
-void tst_QWebEnginePage::setCacheLoadControlAttribute()
-{
-#if !defined(QWEBENGINEPAGE_SETNETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_SETNETWORKACCESSMANAGER");
-#else
- QWebEnginePage page;
- CacheNetworkAccessManager* manager = new CacheNetworkAccessManager(&page);
- page.setNetworkAccessManager(manager);
-
- QNetworkRequest request(QUrl("http://abcdef.abcdef/"));
-
- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysCache);
- page.load(request);
- QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::AlwaysCache);
-
- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
- page.load(request);
- QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::PreferCache);
-
- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::AlwaysNetwork);
- page.load(request);
- QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::AlwaysNetwork);
-
- request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork);
- page.load(request);
- QCOMPARE(manager->lastCacheLoad(), QNetworkRequest::PreferNetwork);
-#endif
-}
-
void tst_QWebEnginePage::setUrlWithPendingLoads()
{
QWebEnginePage page;
diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
index 1fe0f0304..bf5d320b7 100644
--- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
+++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
@@ -29,6 +29,7 @@
#include "../util.h"
#include <QtCore/qbuffer.h>
#include <QtTest/QtTest>
+#include <QtWebEngineCore/qwebengineurlrequestinterceptor.h>
#include <QtWebEngineCore/qwebengineurlrequestjob.h>
#include <QtWebEngineCore/qwebengineurlschemehandler.h>
#include <QtWebEngineWidgets/qwebengineprofile.h>
@@ -52,6 +53,7 @@ private Q_SLOTS:
void urlSchemeHandlerFailRequest();
void urlSchemeHandlerFailOnRead();
void urlSchemeHandlerStreaming();
+ void urlSchemeHandlerRequestHeaders();
void customUserAgent();
void httpAcceptLanguage();
void downloadItem();
@@ -444,6 +446,65 @@ void tst_QWebEngineProfile::urlSchemeHandlerStreaming()
QCOMPARE(toPlainTextSync(view.page()), QString::fromLatin1(result));
}
+class ExtraHeaderInterceptor : public QWebEngineUrlRequestInterceptor
+{
+public:
+ ExtraHeaderInterceptor() { }
+
+ void setExtraHeader(const QByteArray &key, const QByteArray &value)
+ {
+ m_extraKey = key;
+ m_extraValue = value;
+ }
+
+ void interceptRequest(QWebEngineUrlRequestInfo &info) override
+ {
+ if (info.requestUrl().scheme() == QLatin1String("myscheme"))
+ info.setHttpHeader(m_extraKey, m_extraValue);
+ }
+
+ QByteArray m_extraKey;
+ QByteArray m_extraValue;
+};
+
+class RequestHeadersUrlSchemeHandler : public ReplyingUrlSchemeHandler
+{
+public:
+ void setExpectedHeader(const QByteArray &key, const QByteArray &value)
+ {
+ m_expectedKey = key;
+ m_expectedValue = value;
+ }
+ void requestStarted(QWebEngineUrlRequestJob *job) override
+ {
+ const auto requestHeaders = job->requestHeaders();
+ QVERIFY(requestHeaders.contains(m_expectedKey));
+ QCOMPARE(requestHeaders.value(m_expectedKey), m_expectedValue);
+ ReplyingUrlSchemeHandler::requestStarted(job);
+ }
+ QByteArray m_expectedKey;
+ QByteArray m_expectedValue;
+};
+
+void tst_QWebEngineProfile::urlSchemeHandlerRequestHeaders()
+{
+ RequestHeadersUrlSchemeHandler handler;
+ ExtraHeaderInterceptor interceptor;
+
+ handler.setExpectedHeader("Hello", "World");
+ interceptor.setExtraHeader("Hello", "World");
+
+ QWebEngineProfile profile;
+ profile.installUrlSchemeHandler("myscheme", &handler);
+ profile.setRequestInterceptor(&interceptor);
+
+ QWebEnginePage page(&profile);
+ QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+ page.load(QUrl(QStringLiteral("myscheme://whatever")));
+ QVERIFY(loadFinishedSpy.wait());
+}
+
+
void tst_QWebEngineProfile::customUserAgent()
{
QString defaultUserAgent = QWebEngineProfile::defaultProfile()->httpUserAgent();
diff --git a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST
index 7c86a72d6..e8758abcc 100644
--- a/tests/auto/widgets/qwebengineview/BLACKLIST
+++ b/tests/auto/widgets/qwebengineview/BLACKLIST
@@ -6,3 +6,6 @@ osx
[textSelectionOutOfInputField]
*
+
+[changeLocale]
+*
diff --git a/tests/auto/widgets/qwebengineview/resources/image2.png b/tests/auto/widgets/qwebengineview/resources/image2.png
new file mode 100644
index 000000000..8d703640c
--- /dev/null
+++ b/tests/auto/widgets/qwebengineview/resources/image2.png
Binary files differ
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index 3287ca309..f2810101b 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -46,6 +46,7 @@
#include <QTcpSocket>
#include <QStyle>
#include <QtWidgets/qaction.h>
+#include <QtCore/qregularexpression.h>
#define VERIFY_INPUTMETHOD_HINTS(actual, expect) \
QVERIFY(actual == (expect | Qt::ImhNoPredictiveText | Qt::ImhNoTextHandles | Qt::ImhNoEditMenu));
@@ -267,7 +268,7 @@ void tst_QWebEngineView::getWebKitVersion()
void tst_QWebEngineView::changePage_data()
{
QString html = "<html><head><title>%1</title>"
- "<link rel='icon' href='file://" TESTS_SOURCE_DIR "/resources/image2.png'></head></html>";
+ "<link rel='icon' href='qrc:///resources/image2.png'></head></html>";
QUrl urlFrom("data:text/html," + html.arg("TitleFrom"));
QUrl urlTo("data:text/html," + html.arg("TitleTo"));
QUrl nullPage("data:text/html,<html/>");
@@ -1180,7 +1181,7 @@ void tst_QWebEngineView::changeLocale()
QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpyDE.count(), 1, 20000);
QTRY_VERIFY(!toPlainTextSync(viewDE.page()).isEmpty());
- errorLines = toPlainTextSync(viewDE.page()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
+ errorLines = toPlainTextSync(viewDE.page()).split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar"));
QLocale::setDefault(QLocale("en"));
@@ -1190,7 +1191,7 @@ void tst_QWebEngineView::changeLocale()
QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpyEN.count(), 1, 20000);
QTRY_VERIFY(!toPlainTextSync(viewEN.page()).isEmpty());
- errorLines = toPlainTextSync(viewEN.page()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
+ errorLines = toPlainTextSync(viewEN.page()).split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("This site can\xE2\x80\x99t be reached"));
// Reset error page
@@ -1203,7 +1204,7 @@ void tst_QWebEngineView::changeLocale()
QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpyDE.count(), 1, 20000);
QTRY_VERIFY(!toPlainTextSync(viewDE.page()).isEmpty());
- errorLines = toPlainTextSync(viewDE.page()).split(QRegExp("[\r\n]"), QString::SkipEmptyParts);
+ errorLines = toPlainTextSync(viewDE.page()).split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar"));
}
@@ -2634,7 +2635,7 @@ void tst_QWebEngineView::imeJSInputEvents()
view.show();
auto logLines = [&view]() -> QStringList {
- return evaluateJavaScriptSync(view.page(), "log.textContent").toString().split("\n").filter(QRegExp(".+"));
+ return evaluateJavaScriptSync(view.page(), "log.textContent").toString().split("\n").filter(QRegularExpression(".+"));
};
QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.qrc b/tests/auto/widgets/qwebengineview/tst_qwebengineview.qrc
index 53b11bca8..a09be0399 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/keyboardEvents.html</file>
+ <file>resources/image2.png</file>
</qresource>
</RCC>
diff --git a/tests/manual/widgets/inputmethods/testview.cpp b/tests/manual/widgets/inputmethods/testview.cpp
index d41734c2d..14e355caf 100644
--- a/tests/manual/widgets/inputmethods/testview.cpp
+++ b/tests/manual/widgets/inputmethods/testview.cpp
@@ -31,7 +31,7 @@
#include <QDebug>
#include <QFile>
#include <QPushButton>
-#include <QRegExp>
+#include <QRegularExpression>
#include <QStandardItemModel>
#include <QTableView>
#include <QTest>
@@ -77,15 +77,16 @@ void TestView::loadTestData(const QString &testDataPath)
QTextStream testDataStream(&testDataFile);
while (!testDataStream.atEnd()) {
QString line = testDataStream.readLine();
- QRegExp data("^\"(.*)\"\\s*,\\s*(-?\\d+)\\s*,\\s*(-?\\d+)\\s*,\\s*(\\d+)\\s*,\\s*\"(.*)\"\\s*,\\s*\"(.*)\"\\s*$");
- if (!data.exactMatch(line))
+ QRegularExpression data(QRegularExpression::anchoredPattern("^\"(.*)\"\\s*,\\s*(-?\\d+)\\s*,\\s*(-?\\d+)\\s*,\\s*(\\d+)\\s*,\\s*\"(.*)\"\\s*,\\s*\"(.*)\"\\s*$"));
+ QRegularExpressionMatch match = data.match(line);
+ if (!match.hasMatch())
continue;
QStandardItemModel *model = qobject_cast<QStandardItemModel *>(m_tableView->model());
QList<QStandardItem *> row;
- for (int i = 1; i <= data.captureCount(); ++i)
- row.append(new QStandardItem(data.cap(i)));
+ for (int i = 1; i <= match.lastCapturedIndex(); ++i)
+ row.append(new QStandardItem(match.captured(i)));
model->appendRow(row);
}
diff --git a/tests/manual/widgets/webgl/main.cpp b/tests/manual/widgets/webgl/main.cpp
new file mode 100644
index 000000000..364eda8b9
--- /dev/null
+++ b/tests/manual/widgets/webgl/main.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QDebug>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QOperatingSystemVersion>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QSurfaceFormat>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QDesktopWidget>
+#include <QtWidgets/QGroupBox>
+#include <QtWidgets/QHBoxLayout>
+#include <QtWidgets/QMainWindow>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QVBoxLayout>
+#include <QtWebEngineWidgets/QWebEngineView>
+
+// Manual test for checking if WebGL (1 or 2) works.
+// Set environment variable QTWEBENGINE_GL_TYPE to one of the following to try and switch
+// the underlying GL implementation (mostly Windows): "desktop", "gles", "gles3", "software".
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ explicit MainWindow(QWidget *parent = nullptr);
+ QSize sizeHint() const;
+
+private:
+ QWebEngineView *view = nullptr;
+};
+
+MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
+{
+ QWidget *centralWidget = new QWidget;
+
+ QGroupBox *horizontalGroupBox = new QGroupBox;
+ QHBoxLayout *buttonLayout = new QHBoxLayout;
+ QPushButton *exButton1 = new QPushButton(QStringLiteral("Aquarium (WebGL 1)"));
+ QPushButton *exButton2 = new QPushButton(QStringLiteral("Lots of objects (WebGL 1)"));
+ QPushButton *exButton3 = new QPushButton(QStringLiteral("Instanced triangles (WebGL 2)"));
+
+ buttonLayout->addWidget(exButton1);
+ buttonLayout->addWidget(exButton2);
+ buttonLayout->addWidget(exButton3);
+ horizontalGroupBox->setLayout(buttonLayout);
+
+ const QUrl exUrl1 =
+ QUrl(QStringLiteral(
+ "http://webglsamples.org/aquarium/aquarium.html"));
+ const QUrl exUrl2 =
+ QUrl(QStringLiteral(
+ "http://webglsamples.org/lots-o-objects/lots-o-objects-draw-elements.html"));
+ const QUrl exUrl3 =
+ QUrl(QStringLiteral(
+ "http://webglsamples.org/WebGL2Samples/#transform_feedback_instanced"));
+
+ view = new QWebEngineView;
+ connect(exButton1, &QPushButton::clicked, view, [=](){
+ view->setUrl(exUrl1);
+ });
+ connect(exButton2, &QPushButton::clicked, view, [=](){
+ view->setUrl(exUrl2);
+ });
+ connect(exButton3, &QPushButton::clicked, view, [=](){
+ view->setUrl(exUrl3);
+ });
+
+ QVBoxLayout *centralLayout = new QVBoxLayout;
+ centralLayout->addWidget(horizontalGroupBox);
+ centralLayout->addWidget(view, 1);
+
+ centralWidget->setLayout(centralLayout);
+ setCentralWidget(centralWidget);
+
+ view->setUrl(QUrl(QStringLiteral("http://webglsamples.org/aquarium/aquarium.html")));
+ setWindowTitle(tr("WebGL 1 and 2 examples"));
+}
+
+QSize MainWindow::sizeHint() const
+{
+ const QRect desktopRect = QApplication::desktop()->screenGeometry();
+ const QSize size = desktopRect.size() * qreal(0.9);
+ return size;
+}
+
+bool isWindows()
+{
+ return QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows;
+}
+
+// Easy snippets to copy to command line for testing for UNIX only.
+// QTWEBENGINE_GL_TYPE=desktop ./webgl
+// QTWEBENGINE_GL_TYPE=gles ./webgl
+// QTWEBENGINE_GL_TYPE=gles3 ./webgl
+// QTWEBENGINE_GL_TYPE=software ./webgl
+int main(int argc, char *argv[])
+{
+ // Not all options are relevant for all platforms.
+ const QString desktopGL = QStringLiteral("desktop");
+ const QString angle = QStringLiteral("angle"); // Same as gles really, just an alias.
+ const QString gles = QStringLiteral("gles"); // ANGLE on Windows.
+ const QString gles3 = QStringLiteral("gles3"); // ANGLE on Windows.
+ const QString softwareGL = QStringLiteral("software");
+
+ QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+
+ QString glType = qEnvironmentVariable("QTWEBENGINE_GL_TYPE");
+ if (glType.isEmpty()) {
+ if (isWindows())
+ glType = gles3;
+ else
+ glType = desktopGL;
+ }
+
+ if (glType == desktopGL) {
+ QApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
+ qInfo() << QStringLiteral("Trying to use Desktop OpenGL.\n");
+ } else if (glType == gles || glType == gles3 || glType == angle) {
+ QApplication::setAttribute(Qt::AA_UseOpenGLES);
+ if (glType == gles || glType == angle)
+ qInfo() << QStringLiteral("Trying to use OpenGL ES 2.\n");
+ if (glType == gles3)
+ qInfo() << QStringLiteral("Trying to use OpenGL ES 3.\n");
+ } else if (glType == softwareGL) {
+ QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
+ qInfo() << QStringLiteral("Trying to use software OpenGL.\n");
+ }
+
+ if (glType == gles3) {
+ // Set OpenGL ES version 3.
+ QSurfaceFormat format;
+ format.setSamples(4);
+ format.setDepthBufferSize(24);
+ format.setStencilBufferSize(8);
+ format.setVersion(3, 0);
+ QSurfaceFormat::setDefaultFormat(format);
+ }
+
+ QApplication a(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.scenegraph.general=true"));
+ QOpenGLContext *globalSharedContext = QOpenGLContext::globalShareContext();
+ qInfo() << "Global OpenGL context format: " << globalSharedContext->format() << "\n";
+
+ MainWindow w;
+
+ // Move middle-ish.
+ const QRect desktopRect = QApplication::desktop()->screenGeometry();
+ const QSize pos = desktopRect.size() * qreal(0.1);
+ w.move(pos.width(), pos.height());
+
+ w.show();
+
+ return a.exec();
+}
+
+#include "main.moc"
diff --git a/tests/manual/widgets/webgl/webgl.pro b/tests/manual/widgets/webgl/webgl.pro
new file mode 100644
index 000000000..9141d0221
--- /dev/null
+++ b/tests/manual/widgets/webgl/webgl.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+TARGET = webgl
+QT += core gui widgets webenginewidgets
+CONFIG += c++11
+SOURCES += main.cpp
+
diff --git a/tests/manual/widgets/widgets.pro b/tests/manual/widgets/widgets.pro
index f06d3e1c3..34e88f0e3 100644
--- a/tests/manual/widgets/widgets.pro
+++ b/tests/manual/widgets/widgets.pro
@@ -1,4 +1,5 @@
TEMPLATE= subdirs
SUBDIRS += \
- inputmethods
+ inputmethods \
+ webgl
diff --git a/tools/scripts/gn_find_mocables.py b/tools/scripts/gn_find_mocables.py
index d97dcb534..d1f682456 100644
--- a/tools/scripts/gn_find_mocables.py
+++ b/tools/scripts/gn_find_mocables.py
@@ -32,10 +32,9 @@ import os
mocables = set()
includedMocs = set()
-dir = sys.argv[1]
files = sys.argv[2:]
-for f in filter(os.path.isfile, [os.path.join(dir, f) for f in files]):
+for f in filter(os.path.isfile, files):
inBlockComment = False
for line in open(f).readlines():
# Block comments handling
diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py
index 4bf4381cb..4f71185e5 100755
--- a/tools/scripts/take_snapshot.py
+++ b/tools/scripts/take_snapshot.py
@@ -43,7 +43,7 @@ qtwebengine_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..',
os.chdir(qtwebengine_root)
def isInGitBlacklist(file_path):
- # We do need all the gyp files.
+ # We need all the git files.
if ( '.gitignore' in file_path
or '.gitmodules' in file_path
or '.gitattributes' in file_path
@@ -54,33 +54,14 @@ def isInChromiumBlacklist(file_path):
# Filter out empty submodule directories.
if (os.path.isdir(file_path)):
return True
- # 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.
+ # We do need all the gn files.
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
- or '/tests/' in file_path
- or ('/test/' in file_path and
- not '/webrtc/' in file_path and
- not file_path.startswith('net/test/') and
- not file_path.endswith('mock_chrome_application_mac.h') and
- not file_path.endswith('perftimer.h') and
- not file_path.endswith('test-torque.tq') and
- not 'ozone' in file_path and
- not 'fontconfig_util_linux' in file_path and
- not 'core/mojo/test/' in file_path and
- not file_path.startswith('extensions/browser/'))
- or file_path.endswith('.java')
- or file_path.startswith('android_webview')
+ if (file_path.startswith('android_webview')
or file_path.startswith('apps/')
or file_path.startswith('ash/')
or file_path.startswith('base/android')
- or file_path.startswith('breakpad')
or file_path.startswith('buildtools/clang_format/script')
or file_path.startswith('buildtools/third_party/libc++')
or file_path.startswith('buildtools/third_party/libc++abi')
@@ -98,6 +79,7 @@ def isInChromiumBlacklist(file_path):
not 'media/webrtc/desktop_media_list.h' in file_path and
not 'media/webrtc/desktop_streams_registry.' in file_path and
not 'browser/net/chrome_mojo_proxy_resolver_factory.' in file_path and
+ not '/browser/accessibility/' in file_path and
not '/browser/custom_handlers/' in file_path and
not '/browser/devtools/' in file_path and
not '/browser/ui/webui/' in file_path and
@@ -122,25 +104,27 @@ def isInChromiumBlacklist(file_path):
not file_path.endswith('.grdp') and
not file_path.endswith('.json') and
not file_path.endswith('chrome_version.rc.version'))
- or file_path.startswith('chrome_frame')
+ or file_path.startswith('chrome_elf')
or file_path.startswith('chromecast')
or file_path.startswith('chromeos')
or file_path.startswith('cloud_print')
- or file_path.startswith('components/chrome_apps/')
- or file_path.startswith('components/cronet/')
- or file_path.startswith('components/drive/')
- or file_path.startswith('components/invalidation/')
- or file_path.startswith('components/gcm_driver/')
- or file_path.startswith('components/nacl/')
- or file_path.startswith('components/omnibox/')
- or file_path.startswith('components/policy/')
- or file_path.startswith('components/proximity_auth/')
- or (file_path.startswith('components/resources/terms/') and not file_path.endswith('terms_chromium.html'))
- or file_path.startswith('components/rlz/')
- or file_path.startswith('components/sync/') and not file_path.endswith('ordinal.h')
- or file_path.startswith('components/test/')
- or file_path.startswith('components/test_runner/')
- or file_path.startswith('components/translate/')
+ or (file_path.startswith('components/') and (
+ file_path.startswith('components/chrome_apps/')
+ or file_path.startswith('components/cronet/')
+ or file_path.startswith('components/drive/')
+ or file_path.startswith('components/invalidation/')
+ or file_path.startswith('components/gcm_driver/')
+ or file_path.startswith('components/nacl/')
+ or file_path.startswith('components/omnibox/')
+ or file_path.startswith('components/policy/')
+ or file_path.startswith('components/proximity_auth/')
+ or (file_path.startswith('components/resources/terms/') and not file_path.endswith('terms_chromium.html'))
+ or file_path.startswith('components/rlz/')
+ or file_path.startswith('components/sync/') and not file_path.endswith('ordinal.h')
+ or file_path.startswith('components/test/')
+ or file_path.startswith('components/test_runner/')
+ or file_path.startswith('components/translate/')
+ ))
or file_path.startswith('content/public/android/java')
or (file_path.startswith('content/shell') and
not file_path.startswith('content/shell/common') and
@@ -149,7 +133,7 @@ def isInChromiumBlacklist(file_path):
or file_path.startswith('google_update')
or file_path.startswith('ios')
or file_path.startswith('media/base/android/java')
- or file_path.startswith('native_client')
+ or file_path.startswith('native_client_sdk')
or file_path.startswith('net/android/java')
or (file_path.startswith('net/data/') and '_unittest/' in file_path)
or file_path.startswith('net/data/fuzzer_data/')
@@ -157,86 +141,85 @@ def isInChromiumBlacklist(file_path):
or file_path.startswith('rlz')
or file_path.startswith('testing/android')
or file_path.startswith('testing/buildbot')
- or file_path.startswith('third_party/WebKit/LayoutTests')
- or file_path.startswith('third_party/WebKit/ManualTests')
- or file_path.startswith('third_party/WebKit/Source/core/testing/data/')
- or file_path.startswith('third_party/WebKit/Source/devtools/devtools-node-modules')
- or file_path.startswith('third_party/WebKit/PerformanceTests')
- or file_path.startswith('third_party/accessibility-audit')
- or file_path.startswith('third_party/afl')
- or file_path.startswith('third_party/android_')
- or file_path.startswith('third_party/apache-win32')
- or file_path.startswith('third_party/apple_sample_code')
- or file_path.startswith('third_party/ashmem')
- or file_path.startswith('third_party/binutils')
- or file_path.startswith('third_party/bison')
- or file_path.startswith('third_party/blink/perf_tests/')
- or file_path.startswith('third_party/breakpad/src/processor/testdata/')
- or file_path.startswith('third_party/boringssl/crypto_test_data.cc')
- or file_path.startswith('third_party/boringssl/src/fuzz')
- or (file_path.startswith('third_party/cacheinvalidation') and
- not file_path.endswith('isolate'))
- or file_path.startswith('third_party/catapult')
- or file_path.startswith('third_party/chromite')
- or file_path.startswith('third_party/cld_2')
- or file_path.startswith('third_party/closure_compiler')
- or file_path.startswith('third_party/codesighs')
- or file_path.startswith('third_party/colorama')
- or file_path.startswith('third_party/cygwin')
- or file_path.startswith('third_party/cython')
- or file_path.startswith('third_party/deqp')
- or file_path.startswith('third_party/depot_tools')
- or file_path.startswith('third_party/elfutils')
- or file_path.startswith('third_party/freetype-android')
- or file_path.startswith('third_party/google_input_tools')
- or file_path.startswith('third_party/gperf')
- or file_path.startswith('third_party/gnu_binutils')
- or file_path.startswith('third_party/grpc')
- or file_path.startswith('third_party/gtk+')
- or file_path.startswith('third_party/google_appengine_cloudstorage')
- or file_path.startswith('third_party/google_toolbox_for_mac')
- or file_path.startswith('third_party/hunspell_dictionaries')
- or (file_path.startswith('third_party/icu') and file_path.endswith('icudtl_dat.S'))
- or file_path.startswith('third_party/icu/android')
- or file_path.startswith('third_party/icu/ios')
- or file_path.startswith('third_party/instrumented_libraries')
- or file_path.startswith('third_party/jsr-305')
- or file_path.startswith('third_party/junit')
- or file_path.startswith('third_party/lcov')
- or file_path.startswith('third_party/libphonenumber')
- or file_path.startswith('third_party/libaddressinput/src/testdata')
- or file_path.startswith('third_party/libaddressinput/src/common/src/test')
- or file_path.startswith('third_party/libc++')
- or file_path.startswith('third_party/liblouis')
- or file_path.startswith('third_party/lighttpd')
- or file_path.startswith('third_party/libwebm/source/webm_parser/fuzzing')
- or file_path.startswith('third_party/logilab')
- or file_path.startswith('third_party/markdown')
- or file_path.startswith('third_party/mingw-w64')
- or file_path.startswith('third_party/nacl_sdk_binaries')
- or (file_path.startswith('third_party/polymer') and
- not file_path.startswith('third_party/polymer/v1_0/components-chromium/'))
- or file_path.startswith('third_party/openh264/src/res')
- or file_path.startswith('third_party/pdfium/testing/resources')
- or file_path.startswith('third_party/pdfium/tools')
- or file_path.startswith('third_party/pdfsqueeze')
- or file_path.startswith('third_party/pefile')
- or file_path.startswith('third_party/perl')
- or file_path.startswith('third_party/psyco_win32')
- or file_path.startswith('third_party/pylint')
- or file_path.startswith('third_party/scons-2.0.1')
- or file_path.startswith('third_party/sfntly/src/cpp/data/fonts')
- or file_path.startswith('third_party/sfntly/src/java')
- or file_path.startswith('third_party/skia/infra')
- or file_path.startswith('third_party/speech-dispatcher')
- or file_path.startswith('third_party/talloc')
- or file_path.startswith('third_party/trace-viewer')
- or file_path.startswith('third_party/undoview')
- or file_path.startswith('third_party/wayland')
- or file_path.startswith('third_party/webgl')
- or file_path.startswith('third_party/webrtc/resources/')
- or file_path.startswith('third_party/webrtc/third_party/boringssl/crypto_test_data.cc')
- or file_path.startswith('third_party/webrtc/third_party/boringssl/src/fuzz')
+ or (file_path.startswith('third_party/') and (
+ file_path.startswith('third_party/WebKit/LayoutTests')
+ or file_path.startswith('third_party/accessibility-audit')
+ or file_path.startswith('third_party/afl')
+ or file_path.startswith('third_party/android_')
+ or file_path.startswith('third_party/apache-win32')
+ or file_path.startswith('third_party/apple_sample_code')
+ or file_path.startswith('third_party/ashmem')
+ or file_path.startswith('third_party/binutils')
+ or file_path.startswith('third_party/bison')
+ or file_path.startswith('third_party/blink/perf_tests/')
+ or file_path.startswith('third_party/breakpad/src/processor/testdata/')
+ or file_path.startswith('third_party/boringssl/crypto_test_data.cc')
+ or file_path.startswith('third_party/boringssl/src/fuzz')
+ or (file_path.startswith('third_party/cacheinvalidation') and
+ not file_path.endswith('isolate'))
+ or file_path.startswith('third_party/catapult')
+ or file_path.startswith('third_party/chromite')
+ or file_path.startswith('third_party/cld_2')
+ or file_path.startswith('third_party/closure_compiler')
+ or file_path.startswith('third_party/codesighs')
+ or file_path.startswith('third_party/colorama')
+ or file_path.startswith('third_party/cygwin')
+ or file_path.startswith('third_party/cython')
+ or file_path.startswith('third_party/deqp')
+ or file_path.startswith('third_party/depot_tools')
+ or file_path.startswith('third_party/elfutils')
+ or file_path.startswith('third_party/freetype-android')
+ or file_path.startswith('third_party/google_input_tools')
+ or file_path.startswith('third_party/gperf')
+ or file_path.startswith('third_party/gnu_binutils')
+ or file_path.startswith('third_party/grpc')
+ or file_path.startswith('third_party/gtk+')
+ or file_path.startswith('third_party/google_appengine_cloudstorage')
+ or file_path.startswith('third_party/google_toolbox_for_mac')
+ or file_path.startswith('third_party/hunspell_dictionaries')
+ or (file_path.startswith('third_party/icu') and file_path.endswith('icudtl_dat.S'))
+ or file_path.startswith('third_party/icu/android')
+ or file_path.startswith('third_party/icu/ios')
+ or file_path.startswith('third_party/instrumented_libraries')
+ or file_path.startswith('third_party/jsr-305')
+ or file_path.startswith('third_party/junit')
+ or file_path.startswith('third_party/lcov')
+ or file_path.startswith('third_party/libphonenumber')
+ or file_path.startswith('third_party/libaddressinput/src/testdata')
+ or file_path.startswith('third_party/libaddressinput/src/common/src/test')
+ or file_path.startswith('third_party/libc++')
+ or file_path.startswith('third_party/liblouis')
+ or file_path.startswith('third_party/lighttpd')
+ or file_path.startswith('third_party/libwebm/source/webm_parser/fuzzing')
+ or file_path.startswith('third_party/logilab')
+ or file_path.startswith('third_party/markdown')
+ or file_path.startswith('third_party/mingw-w64')
+ or file_path.startswith('third_party/nacl_sdk_binaries')
+ or (file_path.startswith('third_party/polymer') and
+ not file_path.startswith('third_party/polymer/v1_0/components-chromium/'))
+ or file_path.startswith('third_party/openh264/src/res')
+ or file_path.startswith('third_party/pdfium/testing/resources')
+ or file_path.startswith('third_party/pdfium/tools')
+ or file_path.startswith('third_party/pdfsqueeze')
+ or file_path.startswith('third_party/pefile')
+ or file_path.startswith('third_party/perl')
+ or file_path.startswith('third_party/psyco_win32')
+ or file_path.startswith('third_party/pylint')
+ or file_path.startswith('third_party/scons-2.0.1')
+ or file_path.startswith('third_party/sfntly/src/cpp/data/fonts')
+ or file_path.startswith('third_party/sfntly/src/java')
+ or file_path.startswith('third_party/skia/infra')
+ or file_path.startswith('third_party/speech-dispatcher')
+ or file_path.startswith('third_party/swiftshader/third_party/llvm')
+ or file_path.startswith('third_party/talloc')
+ or file_path.startswith('third_party/trace-viewer')
+ or file_path.startswith('third_party/undoview')
+ or file_path.startswith('third_party/wayland')
+ or file_path.startswith('third_party/webgl')
+ or file_path.startswith('third_party/webrtc/resources/')
+ or file_path.startswith('third_party/webrtc/third_party/boringssl/crypto_test_data.cc')
+ or file_path.startswith('third_party/webrtc/third_party/boringssl/src/fuzz')
+ ))
or file_path.startswith('tools/android')
or file_path.startswith('tools/luci_go')
or file_path.startswith('tools/memory_inspector')
@@ -250,7 +233,19 @@ def isInChromiumBlacklist(file_path):
or file_path.startswith('ui/events/ozone/chromeos')
or file_path.startswith('ui/file_manager')
or file_path.startswith('ui/gfx/chromeos')
-
+ or 'testdata/' in file_path
+ or '/tests/' in file_path
+ or ('/test/' in file_path and
+ not '/webrtc/' in file_path and
+ not file_path.startswith('net/test/') and
+ not file_path.endswith('mock_chrome_application_mac.h') and
+ not file_path.endswith('perftimer.h') and
+ not file_path.endswith('test-torque.tq') and
+ not 'ozone' in file_path and
+ not 'clang_coverage' in file_path and
+ not 'fontconfig_util_linux' in file_path and
+ not 'core/mojo/test/' in file_path and
+ not file_path.startswith('extensions/browser/'))
):
return True
return False
@@ -342,6 +337,7 @@ def exportChromium():
files = listFilesInCurrentRepository()
# Add LASTCHANGE files which are not tracked by git.
files.append('build/util/LASTCHANGE')
+ files.append('build/util/LASTCHANGE.committime')
files.append('skia/ext/skia_commit_hash.h')
files.append('gpu/config/gpu_lists_version.h')
print 'copying files to ' + third_party_chromium
diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py
index 27062fbcf..32c3f9d12 100644
--- a/tools/scripts/version_resolver.py
+++ b/tools/scripts/version_resolver.py
@@ -38,8 +38,8 @@ import json
import urllib2
import git_submodule as GitSubmodule
-chromium_version = '69.0.3497.113'
-chromium_branch = '3497'
+chromium_version = '71.0.3578.93'
+chromium_branch = '3578'
ninja_version = 'v1.8.2'
json_url = 'http://omahaproxy.appspot.com/all.json'
@@ -51,7 +51,6 @@ upstream_src_dir = os.path.abspath(snapshot_src_dir + '_upstream')
submodule_blacklist = [
'third_party/WebKit/LayoutTests/w3c/csswg-test'
, 'third_party/WebKit/LayoutTests/w3c/web-platform-tests'
- , 'third_party/jsoncpp/source'
, 'chrome/tools/test/reference_build/chrome_mac'
, 'chrome/tools/test/reference_build/chrome_linux'
, 'chrome/tools/test/reference_build/chrome_win'