summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/examples.pro7
-rw-r--r--examples/webengine/quicknanobrowser/quicknanobrowser.pro2
-rw-r--r--examples/webengine/recipebrowser/doc/images/recipebrowser-demo.jpgbin0 -> 33398 bytes
-rw-r--r--examples/webengine/recipebrowser/doc/src/recipebrowser.qdoc215
-rw-r--r--examples/webengine/recipebrowser/main.cpp66
-rw-r--r--examples/webengine/recipebrowser/recipebrowser.pro14
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/3rdparty/3RDPARTY.md23
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/3rdparty/default.md12
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/3rdparty/markdown.css260
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.min.js6
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/custom.css65
-rw-r--r--examples/webengine/recipebrowser/resources/pages/assets/custom.js57
-rw-r--r--examples/webengine/recipebrowser/resources/pages/burger.html76
-rw-r--r--examples/webengine/recipebrowser/resources/pages/cupcakes.html54
-rw-r--r--examples/webengine/recipebrowser/resources/pages/images/burger.jpgbin0 -> 48882 bytes
-rw-r--r--examples/webengine/recipebrowser/resources/pages/images/cupcakes.jpgbin0 -> 38653 bytes
-rw-r--r--examples/webengine/recipebrowser/resources/pages/images/pasta.jpgbin0 -> 42411 bytes
-rw-r--r--examples/webengine/recipebrowser/resources/pages/images/pizza.jpgbin0 -> 49068 bytes
-rw-r--r--examples/webengine/recipebrowser/resources/pages/images/skewers.jpgbin0 -> 49246 bytes
-rw-r--r--examples/webengine/recipebrowser/resources/pages/images/soup.jpgbin0 -> 49028 bytes
-rw-r--r--examples/webengine/recipebrowser/resources/pages/images/steak.jpgbin0 -> 49202 bytes
-rw-r--r--examples/webengine/recipebrowser/resources/pages/pasta.html57
-rw-r--r--examples/webengine/recipebrowser/resources/pages/pizza.html48
-rw-r--r--examples/webengine/recipebrowser/resources/pages/skewers.html54
-rw-r--r--examples/webengine/recipebrowser/resources/pages/soup.html42
-rw-r--r--examples/webengine/recipebrowser/resources/pages/steak.html68
-rw-r--r--examples/webengine/recipebrowser/resources/qml/RecipeList.qml162
-rw-r--r--examples/webengine/recipebrowser/resources/qml/main.qml153
-rw-r--r--examples/webengine/recipebrowser/resources/resources.qrc28
-rw-r--r--examples/webenginewidgets/demobrowser/browsermainwindow.cpp51
-rw-r--r--examples/webenginewidgets/demobrowser/browsermainwindow.h15
-rw-r--r--examples/webenginewidgets/demobrowser/webview.cpp6
-rw-r--r--examples/webenginewidgets/demobrowser/webview.h1
-rw-r--r--examples/webenginewidgets/spellchecker/data/icon.svg24
-rw-r--r--examples/webenginewidgets/spellchecker/data/index.html33
-rw-r--r--examples/webenginewidgets/spellchecker/data/spellchecker.qrc7
-rw-r--r--examples/webenginewidgets/spellchecker/data/style.css90
-rw-r--r--examples/webenginewidgets/spellchecker/dict/de/README.txt20
-rw-r--r--examples/webenginewidgets/spellchecker/dict/de/de-DE.aff5
-rw-r--r--examples/webenginewidgets/spellchecker/dict/de/de-DE.dic14
-rw-r--r--examples/webenginewidgets/spellchecker/dict/en/README.txt16
-rw-r--r--examples/webenginewidgets/spellchecker/dict/en/en-US.aff5
-rw-r--r--examples/webenginewidgets/spellchecker/dict/en/en-US.dic11
-rw-r--r--examples/webenginewidgets/spellchecker/doc/images/spellchecker-example.pngbin0 -> 15978 bytes
-rw-r--r--examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc134
-rw-r--r--examples/webenginewidgets/spellchecker/main.cpp54
-rw-r--r--examples/webenginewidgets/spellchecker/spellchecker.pro43
-rw-r--r--examples/webenginewidgets/spellchecker/webview.cpp96
-rw-r--r--examples/webenginewidgets/spellchecker/webview.h60
m---------src/3rdparty0
-rw-r--r--src/core/access_token_store_qt.cpp7
-rw-r--r--src/core/access_token_store_qt.h6
-rw-r--r--src/core/api/core_api.pro6
-rw-r--r--src/core/browser_accessibility_manager_qt.cpp5
-rw-r--r--src/core/browser_accessibility_manager_qt.h15
-rw-r--r--src/core/browser_accessibility_qt.cpp4
-rw-r--r--src/core/browser_context_adapter.cpp8
-rw-r--r--src/core/browser_context_adapter_client.h8
-rw-r--r--src/core/browser_context_qt.cpp65
-rw-r--r--src/core/browser_context_qt.h43
-rw-r--r--src/core/certificate_error_controller.cpp3
-rw-r--r--src/core/certificate_error_controller.h3
-rw-r--r--src/core/chrome_qt.gyp56
-rw-r--r--src/core/chromium_gpu_helper.cpp7
-rw-r--r--src/core/chromium_overrides.cpp8
-rw-r--r--src/core/common/qt_messages.h3
-rw-r--r--src/core/common/user_script_data.h3
-rw-r--r--src/core/config/common.pri4
-rw-r--r--src/core/config/desktop_linux.pri3
-rw-r--r--src/core/config/embedded_linux.pri3
-rw-r--r--src/core/config/embedded_qnx.pri1
-rw-r--r--src/core/config/linux.pri19
-rw-r--r--src/core/config/mac_osx.pri3
-rw-r--r--src/core/config/windows.pri11
-rw-r--r--src/core/content_browser_client_qt.cpp117
-rw-r--r--src/core/content_browser_client_qt.h16
-rw-r--r--src/core/content_client_qt.cpp4
-rw-r--r--src/core/content_main_delegate_qt.cpp19
-rw-r--r--src/core/content_main_delegate_qt.h3
-rw-r--r--src/core/cookie_monster_delegate_qt.cpp70
-rw-r--r--src/core/cookie_monster_delegate_qt.h9
-rw-r--r--src/core/core_common.pri1
-rw-r--r--src/core/core_gyp_generator.pro11
-rw-r--r--src/core/core_module.pro8
-rw-r--r--src/core/delegated_frame_node.cpp82
-rw-r--r--src/core/delegated_frame_node.h7
-rw-r--r--src/core/desktop_screen_qt.cpp31
-rw-r--r--src/core/desktop_screen_qt.h20
-rw-r--r--src/core/dev_tools_http_handler_delegate_qt.cpp17
-rw-r--r--src/core/dev_tools_http_handler_delegate_qt.h2
-rw-r--r--src/core/download_manager_delegate_qt.cpp48
-rw-r--r--src/core/download_manager_delegate_qt.h4
-rw-r--r--src/core/file_picker_controller.cpp8
-rw-r--r--src/core/file_picker_controller.h8
-rw-r--r--src/core/gl_context_qt.cpp20
-rw-r--r--src/core/gl_context_qt.h6
-rw-r--r--src/core/gl_surface_qt.cpp76
-rw-r--r--src/core/gl_surface_qt.h2
-rw-r--r--src/core/global_descriptors_qt.h10
-rw-r--r--src/core/gyp_run.pro10
-rw-r--r--src/core/javascript_dialog_manager_qt.cpp10
-rw-r--r--src/core/javascript_dialog_manager_qt.h10
-rw-r--r--src/core/media_capture_devices_dispatcher.cpp62
-rw-r--r--src/core/media_capture_devices_dispatcher.h8
-rw-r--r--src/core/network_delegate_qt.cpp14
-rw-r--r--src/core/network_delegate_qt.h9
-rw-r--r--src/core/ozone_platform_eglfs.cpp26
-rw-r--r--src/core/ozone_platform_eglfs.h23
-rw-r--r--src/core/pdfium_printing_wrapper_qt.cpp231
-rw-r--r--src/core/pdfium_printing_wrapper_qt.h66
-rw-r--r--src/core/permission_manager_qt.cpp33
-rw-r--r--src/core/permission_manager_qt.h12
-rw-r--r--src/core/print_view_manager_base_qt.cpp5
-rw-r--r--src/core/print_view_manager_base_qt.h4
-rw-r--r--src/core/print_view_manager_qt.cpp102
-rw-r--r--src/core/print_view_manager_qt.h8
-rw-r--r--src/core/printing_message_filter_qt.cpp16
-rw-r--r--src/core/printing_message_filter_qt.h8
-rw-r--r--src/core/proxy_config_service_qt.cpp2
-rw-r--r--src/core/proxy_config_service_qt.h5
-rw-r--r--src/core/qtwebengine.gypi12
-rw-r--r--src/core/qtwebengine_extras.gypi17
-rw-r--r--src/core/render_widget_host_view_qt.cpp62
-rw-r--r--src/core/render_widget_host_view_qt.h28
-rw-r--r--src/core/render_widget_host_view_qt_delegate.h19
-rw-r--r--src/core/renderer/content_renderer_client_qt.cpp225
-rw-r--r--src/core/renderer/content_renderer_client_qt.h14
-rw-r--r--src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp401
-rw-r--r--src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.h108
-rw-r--r--src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp77
-rw-r--r--src/core/renderer/pepper/pepper_host_factory_qt.cpp20
-rw-r--r--src/core/renderer/pepper/pepper_host_factory_qt.h2
-rw-r--r--src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp50
-rw-r--r--src/core/renderer/pepper/pepper_renderer_host_factory_qt.h2
-rw-r--r--src/core/renderer/render_frame_observer_qt.cpp8
-rw-r--r--src/core/renderer/render_frame_observer_qt.h1
-rw-r--r--src/core/renderer/render_view_observer_qt.cpp34
-rw-r--r--src/core/renderer/render_view_observer_qt.h7
-rw-r--r--src/core/renderer/user_resource_controller.cpp68
-rw-r--r--src/core/renderer/user_resource_controller.h19
-rw-r--r--src/core/renderer/web_channel_ipc_transport.cpp20
-rw-r--r--src/core/renderer/web_channel_ipc_transport.h13
-rw-r--r--src/core/resource_bundle_qt.cpp70
-rw-r--r--src/core/resource_context_qt.cpp3
-rw-r--r--src/core/resource_dispatcher_host_delegate_qt.cpp3
-rw-r--r--src/core/resource_dispatcher_host_delegate_qt.h8
-rw-r--r--src/core/resources/resources.gyp4
-rw-r--r--src/core/surface_factory_qt.cpp8
-rw-r--r--src/core/type_conversion.cpp2
-rw-r--r--src/core/type_conversion.h2
-rw-r--r--src/core/url_request_context_getter_qt.cpp61
-rw-r--r--src/core/url_request_context_getter_qt.h14
-rw-r--r--src/core/user_script.cpp105
-rw-r--r--src/core/user_script.h3
-rw-r--r--src/core/web_channel_ipc_transport_host.h2
-rw-r--r--src/core/web_contents_adapter.cpp126
-rw-r--r--src/core/web_contents_adapter.h14
-rw-r--r--src/core/web_contents_adapter_client.h167
-rw-r--r--src/core/web_contents_adapter_p.h9
-rw-r--r--src/core/web_contents_delegate_qt.cpp7
-rw-r--r--src/core/web_contents_delegate_qt.h25
-rw-r--r--src/core/web_contents_view_qt.cpp26
-rw-r--r--src/core/web_engine_context.cpp24
-rw-r--r--src/core/web_engine_context.h18
-rw-r--r--src/core/web_engine_library_info.cpp12
-rw-r--r--src/core/web_engine_settings.cpp3
-rw-r--r--src/core/web_engine_settings.h2
-rw-r--r--src/core/web_engine_visited_links_manager.cpp1
-rw-r--r--src/core/yuv_video_node.cpp31
-rw-r--r--src/core/yuv_video_node.h9
-rw-r--r--src/process/process.pro6
-rw-r--r--src/src.pro6
-rw-r--r--src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro3
-rw-r--r--src/webengine/api/qquickwebenginecertificateerror.cpp7
-rw-r--r--src/webengine/api/qquickwebenginecertificateerror_p.h1
-rw-r--r--src/webengine/api/qquickwebenginecontextmenudata.cpp209
-rw-r--r--src/webengine/api/qquickwebenginecontextmenurequest.cpp274
-rw-r--r--src/webengine/api/qquickwebenginecontextmenurequest_p.h (renamed from src/webengine/api/qquickwebenginecontextmenudata_p.h)75
-rw-r--r--src/webengine/api/qquickwebenginedialogrequests.cpp856
-rw-r--r--src/webengine/api/qquickwebenginedialogrequests_p.h265
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem.cpp24
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem_p.h11
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem_p_p.h1
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp84
-rw-r--r--src/webengine/api/qquickwebengineprofile.h9
-rw-r--r--src/webengine/api/qquickwebenginescript.cpp3
-rw-r--r--src/webengine/api/qquickwebenginesettings.cpp43
-rw-r--r--src/webengine/api/qquickwebenginesettings_p.h8
-rw-r--r--src/webengine/api/qquickwebengineview.cpp270
-rw-r--r--src/webengine/api/qquickwebengineview_p.h20
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h18
-rw-r--r--src/webengine/doc/qtwebengine.qdocconf2
-rw-r--r--src/webengine/doc/src/external-resources.qdoc20
-rw-r--r--src/webengine/doc/src/qtwebengine-features.qdoc110
-rw-r--r--src/webengine/doc/src/qtwebengine-overview.qdoc3
-rw-r--r--src/webengine/doc/src/qtwebengine-platform-notes.qdoc4
-rw-r--r--src/webengine/doc/src/qtwebengine-qmlmodule.qdoc4
-rw-r--r--src/webengine/doc/src/webengineview.qdoc109
-rw-r--r--src/webengine/plugin/experimental/plugin.cpp8
-rw-r--r--src/webengine/plugin/plugin.cpp22
-rw-r--r--src/webengine/plugin/plugin.pro2
-rw-r--r--src/webengine/plugin/testsupport/plugin.cpp2
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quick.cpp30
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quick.h5
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp17
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quickwindow.h5
-rw-r--r--src/webengine/ui/PromptDialog.qml4
-rw-r--r--src/webengine/ui/ToolTip.qml91
-rw-r--r--src/webengine/ui/ui.pro3
-rw-r--r--src/webengine/ui2/AlertDialog.qml98
-rw-r--r--src/webengine/ui2/AuthenticationDialog.qml135
-rw-r--r--src/webengine/ui2/ConfirmDialog.qml111
-rw-r--r--src/webengine/ui2/Menu.qml57
-rw-r--r--src/webengine/ui2/MenuItem.qml44
-rw-r--r--src/webengine/ui2/MenuSeparator.qml (renamed from tests/quicktestbrowser/ContextMenuExtras.qml)41
-rw-r--r--src/webengine/ui2/PromptDialog.qml114
-rw-r--r--src/webengine/ui2/ToolTip.qml45
-rw-r--r--src/webengine/ui2/information.pngbin0 -> 254 bytes
-rw-r--r--src/webengine/ui2/qmldir2
-rw-r--r--src/webengine/ui2/question.pngbin0 -> 257 bytes
-rw-r--r--src/webengine/ui2/ui2.pro18
-rw-r--r--src/webengine/ui_delegates_manager.cpp232
-rw-r--r--src/webengine/ui_delegates_manager.h44
-rw-r--r--src/webengine/webengine.pro6
-rw-r--r--src/webenginewidgets/api/qwebenginecertificateerror.cpp2
-rw-r--r--src/webenginewidgets/api/qwebenginecertificateerror.h1
-rw-r--r--src/webenginewidgets/api/qwebenginecontextmenudata.cpp38
-rw-r--r--src/webenginewidgets/api/qwebenginecontextmenudata.h2
-rw-r--r--src/webenginewidgets/api/qwebenginedownloaditem.cpp29
-rw-r--r--src/webenginewidgets/api/qwebenginedownloaditem.h9
-rw-r--r--src/webenginewidgets/api/qwebenginedownloaditem_p.h1
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp253
-rw-r--r--src/webenginewidgets/api/qwebenginepage.h21
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h7
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp70
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.h5
-rw-r--r--src/webenginewidgets/api/qwebenginescript.cpp3
-rw-r--r--src/webenginewidgets/api/qwebenginesettings.cpp5
-rw-r--r--src/webenginewidgets/api/qwebenginesettings.h4
-rw-r--r--src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc5
-rw-r--r--src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc8
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp174
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h25
-rw-r--r--src/webenginewidgets/webenginewidgets.pro2
-rw-r--r--sync.profile1
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp24
-rw-r--r--tests/auto/quick/qmltests/BLACKLIST3
-rw-r--r--tests/auto/quick/qmltests/data/forms.html12
-rw-r--r--tests/auto/quick/qmltests/data/script-with-metadata.js10
-rw-r--r--tests/auto/quick/qmltests/data/tst_download.qml2
-rw-r--r--tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml136
-rw-r--r--tests/auto/quick/qmltests/data/tst_formValidation.qml24
-rw-r--r--tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml1
-rw-r--r--tests/auto/quick/qmltests/data/tst_runJavaScript.qml1
-rw-r--r--tests/auto/quick/qmltests/data/tst_userScripts.qml22
-rw-r--r--tests/auto/quick/qmltests/data/tst_viewSource.qml127
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro2
-rw-r--r--tests/auto/quick/qquickwebengineview/BLACKLIST3
-rw-r--r--tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp37
-rw-r--r--tests/auto/widgets/qwebenginepage/BLACKLIST5
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/test1.html7
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp228
-rw-r--r--tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp20
-rw-r--r--tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp23
-rw-r--r--tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp13
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp134
-rw-r--r--tests/quicktestbrowser/BrowserWindow.qml5
-rw-r--r--tests/quicktestbrowser/DownloadView.qml1
-rw-r--r--tests/quicktestbrowser/quicktestbrowser.pro2
-rw-r--r--tests/quicktestbrowser/resources.qrc1
-rw-r--r--tools/qmake/mkspecs/features/configure.prf11
-rw-r--r--tools/qmake/mkspecs/features/functions.prf56
-rw-r--r--tools/qmake/mkspecs/features/gyp_generator.prf2
-rwxr-xr-xtools/scripts/take_snapshot.py83
-rw-r--r--tools/scripts/version_resolver.py6
-rwxr-xr-xtools/scripts/windeploy-examples.py393
277 files changed, 9069 insertions, 2250 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 9d4004a02..5237fb5fd 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,4 +2,4 @@ QMAKEPATH += $$PWD/tools/qmake
load(qt_build_config)
CONFIG += warning_clean
-MODULE_VERSION = 5.7.1
+MODULE_VERSION = 5.8.0
diff --git a/examples/examples.pro b/examples/examples.pro
index 0de2ec505..f15007e83 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -13,5 +13,10 @@ qtHaveModule(webenginewidgets) {
webenginewidgets/cookiebrowser \
webenginewidgets/demobrowser \
webenginewidgets/markdowneditor \
- webenginewidgets/simplebrowser \
+ webenginewidgets/simplebrowser
+
+ !contains(WEBENGINE_CONFIG, no_spellcheck):!osx:!cross_compile {
+ SUBDIRS += webenginewidgets/spellchecker
+ }
+
}
diff --git a/examples/webengine/quicknanobrowser/quicknanobrowser.pro b/examples/webengine/quicknanobrowser/quicknanobrowser.pro
index 6cf556984..5a27f5fd4 100644
--- a/examples/webengine/quicknanobrowser/quicknanobrowser.pro
+++ b/examples/webengine/quicknanobrowser/quicknanobrowser.pro
@@ -1,4 +1,4 @@
-requires(contains(QT_CONFIG, accessibility))
+requires(qtConfig(accessibility))
TEMPLATE = app
TARGET = quicknanobrowser
diff --git a/examples/webengine/recipebrowser/doc/images/recipebrowser-demo.jpg b/examples/webengine/recipebrowser/doc/images/recipebrowser-demo.jpg
new file mode 100644
index 000000000..761ad3576
--- /dev/null
+++ b/examples/webengine/recipebrowser/doc/images/recipebrowser-demo.jpg
Binary files differ
diff --git a/examples/webengine/recipebrowser/doc/src/recipebrowser.qdoc b/examples/webengine/recipebrowser/doc/src/recipebrowser.qdoc
new file mode 100644
index 000000000..5327a0b26
--- /dev/null
+++ b/examples/webengine/recipebrowser/doc/src/recipebrowser.qdoc
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example webengine/recipebrowser
+ \title WebEngine Recipe Browser
+ \ingroup webengine-examples
+ \brief A small hybrid application based on the WebEngineView QML type and Qt Quick Controls 2.
+
+ \image recipebrowser-demo.jpg
+
+ \e {Recipe Browser} demonstrates how to use the \l{WebEngineView} item, \l{Qt Quick} items, and
+ \l{Qt Quick Controls 2} items to develop a small hybrid web browser application.
+ A \l{ListView}-based item is used to display a list of recipe names. Clicking on
+ a name causes the web view to load the respective recipe page. The overall appearance
+ of the application is provided by the \l{Qt Quick Controls 2} items, which have their active
+ style set to the \l{Material Style}{Material} style. The web content is a mix of HTML and
+ Markdown source compiled to HTML, along with CSS and JavaScript.
+
+ \include examples-run.qdocinc
+
+ \section1 C++ Code
+
+ In \c main.cpp, we use the \l{QGuiApplication} and \l{QQmlApplicationEngine}
+ classes to set up and load the main QML file. We call \l{QtWebEngine::initialize} so we can use
+ \l{WebEngineView} in our QML code. We enable high DPI screen support by setting the
+ \l{Qt::AA_EnableHighDpiScaling} attribute. We set the default Qt Quick Controls 2 style
+ to the Material style, so we do not have to specify it for each new item we add. Finally, we use
+ a C++ define to check whether the application is compiled for an embedded platform.
+ The value will be used in the main QML code to determine the window size.
+
+ \quotefromfile webengine/recipebrowser/main.cpp
+ \skipto #include
+ \printuntil }
+
+ \section1 QML Code
+
+ In the \c main.qml file, we first create a top-level window and set a title for it. We also set
+ up the size of the window depending on its primary orientation as well as the platform, so that
+ the application is usable on both desktop and embedded platforms. On desktop, the size
+ is constrained by a minimum of 320x480 pixels up to the maximum size that the screen supports.
+ The default window size is 1024 pixels wide and 768 pixels high in landscape orientation.
+ On embedded devices, the window will occupy the whole screen.
+
+ \quotefromfile webengine/recipebrowser/resources/qml/main.qml
+ \skipto ApplicationWindow
+ \printuntil minimumHeight
+
+ Next, we add a \l{RowLayout} item so we can divide the window into two parts: one being a
+ custom \c RecipeList item containing the recipe titles, and the other being the
+ \l{WebEngineView}, which shows the recipe details. The spacing is set to zero so the items are
+ positioned directly next to each other.
+
+ \printuntil RecipeList
+ \dots 16
+ \skipuntil onRecipeSelected
+ \printline }
+ \printuntil WebEngineView
+ \dots 16
+ \skipuntil busy.running = true
+ \skipline }
+ \skipline }
+ \printline }
+ \printline }
+
+ The \c RecipeList item has a few \l{Layout}{attached Layout properties}, in order to scale the
+ item to a maximum of one third of the layout width. We give the item focus, so that the keyboard
+ can be used to navigate the recipes, in addition to using mouse and touch. We also add a handler
+ for the custom \c recipeSelected signal, to tell the WebEngineView to load the URL of the
+ selected recipe.
+
+ \quotefromfile webengine/recipebrowser/resources/qml/main.qml
+ \skipto RecipeList
+ \printuntil }
+
+ The WebEngineView has similar layout properties, to make it occupy two thirds of the layout
+ width.
+
+ \skipto WebEngineView
+ \printuntil KeyNavigation.priority
+
+ We then disable the \l{WebEngineSettings::focusOnNavigationEnabled}{focusOnNavigationEnabled}
+ setting to make sure that the \l{WebEngineView} does not steal focus from the \c RecipeList
+ item every time its URL is changed. This allows the user to continue navigating through the
+ recipes using the keyboard.
+
+ \skipto focusOnNavigationEnabled
+ \printuntil focusOnNavigationEnabled
+
+ When the application starts, instead of directly showing the \l{WebEngineView}, we show a
+ placeholder \l{Rectangle} with a \l{BusyIndicator} to provide a nicer user experience while the
+ application is loading. Once the first page in the view is loaded, we start a \l{Timer} that
+ will hide the placeholder and show the actual page. The delay provides more time for the recipe
+ images to load, so that when the view is shown, the page is completely rendered. The timer also
+ shows a help \l{ToolTip} that informs the user on how to navigate the recipes.
+
+ \printuntil busy.running = true
+ \printline }
+ \printline }
+ \printline }
+
+ Let's see what the \c RecipeList item looks like from the inside. The root item is a
+ FocusScope to allow transferring focus to the child ListView whenever the root item receives
+ focus. We also declare a custom \c recipeSelected signal, which will be emitted when the current
+ item of the ListView changes.
+
+ \quotefromfile webengine/recipebrowser/resources/qml/RecipeList.qml
+ \skipto FocusScope
+ \printuntil recipeSelected
+
+ A ColumnLayout holds a header \l{Label} above the ListView, and the ListView itself.
+ Again, we set the spacing to zero and make sure the layout occupies the whole space of
+ the parent item.
+
+ \skipto ColumnLayout
+ \printuntil anchors.fill
+
+ Inside the layout there is a styled \l{ToolBar} item, with a \l{Label} inside of it serving as
+ the ListView header.
+
+ \skipto ToolBar
+ \printuntil Label
+ \printuntil }
+ \printuntil }
+
+ The second item inside the layout is a \l{ListView}, whose contents will fill the remaining
+ space in the layout. We set \l{Item::}{clip} to true, so that the delegates that are scrolled
+ up are not seen under the ToolBar item. We set \l{Item::}{focus} to true, so the ListView gains
+ focus when the FocusScope does. We add a vertical scroll bar, so the user can scroll through the
+ recipes if the window size is small. We also specify the recipe model to be used by the
+ ListView as described later in this topic.
+
+ \skipto ListView
+ \printuntil model
+
+ We have an \l{ItemDelegate} set as the ListView delegate, which displays the
+ recipe title. The contentItem is a \l{Text} item, customized with a few properties to adjust the
+ visual appearance and position of the text. We create a binding to the current delegate's model
+ URL, so we can access the respective URL outside the delegate itself. We set the
+ \l{ItemDelegate::}{highlighted} property to \c true whenever the item is the current one in the
+ ListView to provide visual feedback. And we set the focus on the ListView whenever a delegate
+ is clicked, so that keyboard navigation works in case the focus was previously in the
+ WebEngineView.
+
+ \skipto delegate
+ \printuntil onClicked
+ \printuntil }
+ \printuntil }
+
+ A handler is defined for the \c currentItemChanged signal to emit our own \c recipeSelected
+ signal with the URL that the WebEngineView should load.
+
+ \skipto onCurrentItemChanged
+ \printuntil }
+
+ We use a \l{ListModel} with seven \l{ListElement}s, each of which contains a recipe
+ title and the URL to an HTML page contained in a resource file. The model is used to populate
+ the ListView with the recipes and to show the recipe details in the WebEngineView.
+
+ \skipto ListModel
+ \printuntil Cupcakes
+ \printuntil }
+ \printuntil }
+
+ We use a \l{ToolTip} item that is displayed on application startup to inform the users
+ how they can navigate and view the details of each recipe. The ToolTip is shown using the
+ \c showHelp method, which is invoked by the \l{Timer} in the main.qml file.
+
+ \skipto ToolTip
+ \printuntil help.open()
+ \printuntil }
+ \printuntil }
+
+ An example of a recipe page can be seen below. The page uses two stylesheets and
+ two JavaScript files:
+ \list
+ \li \l{http://kevinburke.bitbucket.org/markdowncss/}{markdown.css} is
+ a markdown-friendly stylesheet created by Kevin Burke
+ \li \l{https://github.com/chjj/marked}{marked.min.js} is a markdown parser and
+ compiler designed for speed written by Christopher Jeffrey
+ \li custom.css makes some small styling adjustments to the final recipe page
+ \li custom.js is used to invoke the conversion of the recipe content (which is written in
+ markdown syntax) into HTML
+ \endlist
+
+ The images on the pages are loaded from the compiled resource file.
+
+ \quotefromfile webengine/recipebrowser/resources/pages/soup.html
+ \printuntil </html>
+
+*/
diff --git a/examples/webengine/recipebrowser/main.cpp b/examples/webengine/recipebrowser/main.cpp
new file mode 100644
index 000000000..a4251c3ea
--- /dev/null
+++ b/examples/webengine/recipebrowser/main.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QQmlContext>
+#include <QQuickStyle>
+#include <qtwebengineglobal.h>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+ QGuiApplication app(argc, argv);
+ QtWebEngine::initialize();
+
+ QQuickStyle::setStyle(QStringLiteral("Material"));
+
+ QQmlApplicationEngine engine;
+
+ bool isEmbedded = false;
+#ifdef QTWEBENGINE_RECIPE_BROWSER_EMBEDDED
+ isEmbedded = true;
+#endif
+ engine.rootContext()->setContextProperty(QStringLiteral("isEmbedded"), isEmbedded);
+
+ engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
+
+ return app.exec();
+}
diff --git a/examples/webengine/recipebrowser/recipebrowser.pro b/examples/webengine/recipebrowser/recipebrowser.pro
new file mode 100644
index 000000000..ea6db13fb
--- /dev/null
+++ b/examples/webengine/recipebrowser/recipebrowser.pro
@@ -0,0 +1,14 @@
+TEMPLATE = app
+
+QT += quick qml quickcontrols2 webengine
+
+cross_compile {
+ posix|qnx|linux: DEFINES += QTWEBENGINE_RECIPE_BROWSER_EMBEDDED
+}
+
+SOURCES += main.cpp
+
+RESOURCES += resources/resources.qrc
+
+target.path = $$[QT_INSTALL_EXAMPLES]/webengine/recipebrowser
+INSTALLS += target
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/3RDPARTY.md b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/3RDPARTY.md
new file mode 100644
index 000000000..9e91ab302
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/3RDPARTY.md
@@ -0,0 +1,23 @@
+## markd license
+
+```
+Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+```
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/default.md b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/default.md
new file mode 100644
index 000000000..8f9c807aa
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/default.md
@@ -0,0 +1,12 @@
+## WebEngine Markdown Editor Example
+
+This example uses [QWebEngineView](http://doc.qt.io/qt-5/qwebengineview.html)
+to preview text written using the [Markdown](https://en.wikipedia.org/wiki/Markdown)
+syntax.
+
+### Acknowledgments
+
+The conversion from Markdown to HTML is done with the help of the
+[marked JavaScript library](https://github.com/chjj/marked) by _Christopher Jeffrey_.
+The [style sheet](http://kevinburke.bitbucket.org/markdowncss/markdown.css)
+was created by _Kevin Burke_.
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/markdown.css b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/markdown.css
new file mode 100644
index 000000000..24fc2ffe2
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/markdown.css
@@ -0,0 +1,260 @@
+body{
+ margin: 0 auto;
+ font-family: Georgia, Palatino, serif;
+ color: #444444;
+ line-height: 1;
+ max-width: 960px;
+ padding: 30px;
+}
+h1, h2, h3, h4 {
+ color: #111111;
+ font-weight: 400;
+}
+h1, h2, h3, h4, h5, p {
+ margin-bottom: 24px;
+ padding: 0;
+}
+h1 {
+ font-size: 48px;
+}
+h2 {
+ font-size: 36px;
+ /* The bottom margin is small. It's designed to be used with gray meta text
+ * below a post title. */
+ margin: 24px 0 6px;
+}
+h3 {
+ font-size: 24px;
+}
+h4 {
+ font-size: 21px;
+}
+h5 {
+ font-size: 18px;
+}
+a {
+ color: #0099ff;
+ margin: 0;
+ padding: 0;
+ vertical-align: baseline;
+}
+a:hover {
+ text-decoration: none;
+ color: #ff6600;
+}
+a:visited {
+ color: purple;
+}
+ul, ol {
+ padding: 0;
+ margin: 0;
+}
+li {
+ line-height: 24px;
+}
+li ul, li ul {
+ margin-left: 24px;
+}
+p, ul, ol {
+ font-size: 16px;
+ line-height: 24px;
+ max-width: 540px;
+}
+pre {
+ padding: 0px 24px;
+ max-width: 800px;
+ white-space: pre-wrap;
+}
+code {
+ font-family: Consolas, Monaco, Andale Mono, monospace;
+ line-height: 1.5;
+ font-size: 13px;
+}
+aside {
+ display: block;
+ float: right;
+ width: 390px;
+}
+blockquote {
+ border-left:.5em solid #eee;
+ padding: 0 2em;
+ margin-left:0;
+ max-width: 476px;
+}
+blockquote cite {
+ font-size:14px;
+ line-height:20px;
+ color:#bfbfbf;
+}
+blockquote cite:before {
+ content: '\2014 \00A0';
+}
+
+blockquote p {
+ color: #666;
+ max-width: 460px;
+}
+hr {
+ width: 540px;
+ text-align: left;
+ margin: 0 auto 0 0;
+ color: #999;
+}
+
+/* Code below this line is copyright Twitter Inc. */
+
+button,
+input,
+select,
+textarea {
+ font-size: 100%;
+ margin: 0;
+ vertical-align: baseline;
+ *vertical-align: middle;
+}
+button, input {
+ line-height: normal;
+ *overflow: visible;
+}
+button::-moz-focus-inner, input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+button,
+input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ cursor: pointer;
+ -webkit-appearance: button;
+}
+input[type=checkbox], input[type=radio] {
+ cursor: pointer;
+}
+/* override default chrome & firefox settings */
+input:not([type="image"]), textarea {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+
+input[type="search"] {
+ -webkit-appearance: textfield;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+label,
+input,
+select,
+textarea {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: normal;
+ margin-bottom: 18px;
+}
+input[type=checkbox], input[type=radio] {
+ cursor: pointer;
+ margin-bottom: 0;
+}
+input[type=text],
+input[type=password],
+textarea,
+select {
+ display: inline-block;
+ width: 210px;
+ padding: 4px;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: 18px;
+ height: 18px;
+ color: #808080;
+ border: 1px solid #ccc;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+select, input[type=file] {
+ height: 27px;
+ line-height: 27px;
+}
+textarea {
+ height: auto;
+}
+
+/* grey out placeholders */
+:-moz-placeholder {
+ color: #bfbfbf;
+}
+::-webkit-input-placeholder {
+ color: #bfbfbf;
+}
+
+input[type=text],
+input[type=password],
+select,
+textarea {
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
+ transition: border linear 0.2s, box-shadow linear 0.2s;
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+input[type=text]:focus, input[type=password]:focus, textarea:focus {
+ outline: none;
+ border-color: rgba(82, 168, 236, 0.8);
+ -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
+ -moz-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
+ box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6);
+}
+
+/* buttons */
+button {
+ display: inline-block;
+ padding: 4px 14px;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
+ line-height: 18px;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
+ background-color: #0064cd;
+ background-repeat: repeat-x;
+ background-image: -khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));
+ background-image: -moz-linear-gradient(top, #049cdb, #0064cd);
+ background-image: -ms-linear-gradient(top, #049cdb, #0064cd);
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));
+ background-image: -webkit-linear-gradient(top, #049cdb, #0064cd);
+ background-image: -o-linear-gradient(top, #049cdb, #0064cd);
+ background-image: linear-gradient(top, #049cdb, #0064cd);
+ color: #fff;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+ border: 1px solid #004b9a;
+ border-bottom-color: #003f81;
+ -webkit-transition: 0.1s linear all;
+ -moz-transition: 0.1s linear all;
+ transition: 0.1s linear all;
+ border-color: #0064cd #0064cd #003f81;
+ border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
+}
+button:hover {
+ color: #fff;
+ background-position: 0 -15px;
+ text-decoration: none;
+}
+button:active {
+ -webkit-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ -moz-box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 3px 7px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
+}
+button::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.min.js b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.min.js
new file mode 100644
index 000000000..f679a4776
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/assets/3rdparty/marked.min.js
@@ -0,0 +1,6 @@
+/**
+ * marked - a markdown parser
+ * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
+ * https://github.com/chjj/marked
+ */
+(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,"gm")(/bull/g,block.bullet)();block.list=replace(block.list)(/bull/g,block.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+block.def.source+")")();block.blockquote=replace(block.blockquote)("def",block.def)();block._tag="(?!(?:"+"a|em|strong|small|s|cite|q|dfn|abbr|data|time|code"+"|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo"+"|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b";block.html=replace(block.html)("comment",/<!--[\s\S]*?-->/)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)(/tag/g,block._tag)();block.paragraph=replace(block.paragraph)("hr",block.hr)("heading",block.heading)("lheading",block.lheading)("blockquote",block.blockquote)("tag","<"+block._tag)("def",block.def)();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/});block.gfm.paragraph=replace(block.paragraph)("(?!","(?!"+block.gfm.fences.source.replace("\\1","\\2")+"|"+block.list.source.replace("\\1","\\3")+"|")();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables}else{this.rules=block.gfm}}}Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src)};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n");return this.token(src,true)};Lexer.prototype.token=function(src,top,bq){var src=src.replace(/^ +$/gm,""),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:"space"})}}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,"");this.tokens.push({type:"code",text:!this.options.pedantic?cap.replace(/\n+$/,""):cap});continue}if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"code",lang:cap[2],text:cap[3]||""});continue}if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[1].length,text:cap[2]});continue}if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */)}this.tokens.push(item);continue}if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"heading",depth:cap[2]==="="?1:2,text:cap[1]});continue}if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"hr"});continue}if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"blockquote_start"});cap=cap[0].replace(/^ *> ?/gm,"");this.token(cap,top,true);this.tokens.push({type:"blockquote_end"});continue}if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);bull=cap[2];this.tokens.push({type:"list_start",ordered:bull.length>1});cap=cap[0].match(this.rules.item);next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,"");if(~item.indexOf("\n ")){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp("^ {1,"+space+"}","gm"),""):item.replace(/^ {1,4}/gm,"")}if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull.length>1&&b.length>1)){src=cap.slice(i+1).join("\n")+src;i=l-1}}loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item.charAt(item.length-1)==="\n";if(!loose)loose=next}this.tokens.push({type:loose?"loose_item_start":"list_item_start"});this.token(item,false,bq);this.tokens.push({type:"list_item_end"})}this.tokens.push({type:"list_end"});continue}if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&(cap[1]==="pre"||cap[1]==="script"||cap[1]==="style"),text:cap[0]});continue}if(!bq&&top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue}if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:"table",header:cap[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,"").split("\n")};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]="right"}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]="center"}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]="left"}else{item.align[i]=null}}for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,"").split(/ *\| */)}this.tokens.push(item);continue}if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:"paragraph",text:cap[1].charAt(cap[1].length-1)==="\n"?cap[1].slice(0,-1):cap[1]});continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:"text",text:cap[0]});continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return this.tokens};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)("inside",inline._inside)("href",inline._href)();inline.reflink=replace(inline.reflink)("inside",inline._inside)();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)("]|","~]|")("|","|https?://|")()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)("{2,}","*")(),text:replace(inline.gfm.text)("{2,}","*")()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;this.renderer=this.options.renderer||new Renderer;this.renderer.options=this.options;if(!this.links){throw new Error("Tokens array requires a `links` property.")}if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks}else{this.rules=inline.gfm}}else if(this.options.pedantic){this.rules=inline.pedantic}}InlineLexer.rules=inline;InlineLexer.output=function(src,links,options){var inline=new InlineLexer(links,options);return inline.output(src)};InlineLexer.prototype.output=function(src){var out="",link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue}if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==="@"){text=cap[1].charAt(6)===":"?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle("mailto:")+text}else{text=escape(cap[1]);href=text}out+=this.renderer.link(href,null,text);continue}if(!this.inLink&&(cap=this.rules.url.exec(src))){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+=this.renderer.link(href,null,text);continue}if(cap=this.rules.tag.exec(src)){if(!this.inLink&&/^<a /i.test(cap[0])){this.inLink=true}else if(this.inLink&&/^<\/a>/i.test(cap[0])){this.inLink=false}src=src.substring(cap[0].length);out+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(cap[0]):escape(cap[0]):cap[0];continue}if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);this.inLink=true;out+=this.outputLink(cap,{href:cap[2],title:cap[3]});this.inLink=false;continue}if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g," ");link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0].charAt(0);src=cap[0].substring(1)+src;continue}this.inLink=true;out+=this.outputLink(cap,link);this.inLink=false;continue}if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.strong(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.em(this.output(cap[2]||cap[1]));continue}if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.codespan(escape(cap[2],true));continue}if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.br();continue}if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.del(this.output(cap[1]));continue}if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=this.renderer.text(escape(this.smartypants(cap[0])));continue}if(src){throw new Error("Infinite loop on byte: "+src.charCodeAt(0))}}return out};InlineLexer.prototype.outputLink=function(cap,link){var href=escape(link.href),title=link.title?escape(link.title):null;return cap[0].charAt(0)!=="!"?this.renderer.link(href,title,this.output(cap[1])):this.renderer.image(href,title,escape(cap[1]))};InlineLexer.prototype.smartypants=function(text){if(!this.options.smartypants)return text;return text.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…")};InlineLexer.prototype.mangle=function(text){if(!this.options.mangle)return text;var out="",l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>.5){ch="x"+ch.toString(16)}out+="&#"+ch+";"}return out};function Renderer(options){this.options=options||{}}Renderer.prototype.code=function(code,lang,escaped){if(this.options.highlight){var out=this.options.highlight(code,lang);if(out!=null&&out!==code){escaped=true;code=out}}if(!lang){return"<pre><code>"+(escaped?code:escape(code,true))+"\n</code></pre>"}return'<pre><code class="'+this.options.langPrefix+escape(lang,true)+'">'+(escaped?code:escape(code,true))+"\n</code></pre>\n"};Renderer.prototype.blockquote=function(quote){return"<blockquote>\n"+quote+"</blockquote>\n"};Renderer.prototype.html=function(html){return html};Renderer.prototype.heading=function(text,level,raw){return"<h"+level+' id="'+this.options.headerPrefix+raw.toLowerCase().replace(/[^\w]+/g,"-")+'">'+text+"</h"+level+">\n"};Renderer.prototype.hr=function(){return this.options.xhtml?"<hr/>\n":"<hr>\n"};Renderer.prototype.list=function(body,ordered){var type=ordered?"ol":"ul";return"<"+type+">\n"+body+"</"+type+">\n"};Renderer.prototype.listitem=function(text){return"<li>"+text+"</li>\n"};Renderer.prototype.paragraph=function(text){return"<p>"+text+"</p>\n"};Renderer.prototype.table=function(header,body){return"<table>\n"+"<thead>\n"+header+"</thead>\n"+"<tbody>\n"+body+"</tbody>\n"+"</table>\n"};Renderer.prototype.tablerow=function(content){return"<tr>\n"+content+"</tr>\n"};Renderer.prototype.tablecell=function(content,flags){var type=flags.header?"th":"td";var tag=flags.align?"<"+type+' style="text-align:'+flags.align+'">':"<"+type+">";return tag+content+"</"+type+">\n"};Renderer.prototype.strong=function(text){return"<strong>"+text+"</strong>"};Renderer.prototype.em=function(text){return"<em>"+text+"</em>"};Renderer.prototype.codespan=function(text){return"<code>"+text+"</code>"};Renderer.prototype.br=function(){return this.options.xhtml?"<br/>":"<br>"};Renderer.prototype.del=function(text){return"<del>"+text+"</del>"};Renderer.prototype.link=function(href,title,text){if(this.options.sanitize){try{var prot=decodeURIComponent(unescape(href)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(prot.indexOf("javascript:")===0||prot.indexOf("vbscript:")===0){return""}}var out='<a href="'+href+'"';if(title){out+=' title="'+title+'"'}out+=">"+text+"</a>";return out};Renderer.prototype.image=function(href,title,text){var out='<img src="'+href+'" alt="'+text+'"';if(title){out+=' title="'+title+'"'}out+=this.options.xhtml?"/>":">";return out};Renderer.prototype.text=function(text){return text};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;this.options.renderer=this.options.renderer||new Renderer;this.renderer=this.options.renderer;this.renderer.options=this.options}Parser.parse=function(src,options,renderer){var parser=new Parser(options,renderer);return parser.parse(src)};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options,this.renderer);this.tokens=src.reverse();var out="";while(this.next()){out+=this.tok()}return out};Parser.prototype.next=function(){return this.token=this.tokens.pop()};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==="text"){body+="\n"+this.next().text}return this.inline.output(body)};Parser.prototype.tok=function(){switch(this.token.type){case"space":{return""}case"hr":{return this.renderer.hr()}case"heading":{return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text)}case"code":{return this.renderer.code(this.token.text,this.token.lang,this.token.escaped)}case"table":{var header="",body="",i,row,cell,flags,j;cell="";for(i=0;i<this.token.header.length;i++){flags={header:true,align:this.token.align[i]};cell+=this.renderer.tablecell(this.inline.output(this.token.header[i]),{header:true,align:this.token.align[i]})}header+=this.renderer.tablerow(cell);for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];cell="";for(j=0;j<row.length;j++){cell+=this.renderer.tablecell(this.inline.output(row[j]),{header:false,align:this.token.align[j]})}body+=this.renderer.tablerow(cell)}return this.renderer.table(header,body)}case"blockquote_start":{var body="";while(this.next().type!=="blockquote_end"){body+=this.tok()}return this.renderer.blockquote(body)}case"list_start":{var body="",ordered=this.token.ordered;while(this.next().type!=="list_end"){body+=this.tok()}return this.renderer.list(body,ordered)}case"list_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.token.type==="text"?this.parseText():this.tok()}return this.renderer.listitem(body)}case"loose_item_start":{var body="";while(this.next().type!=="list_item_end"){body+=this.tok()}return this.renderer.listitem(body)}case"html":{var html=!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;return this.renderer.html(html)}case"paragraph":{return this.renderer.paragraph(this.inline.output(this.token.text))}case"text":{return this.renderer.paragraph(this.parseText())}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function unescape(html){return html.replace(/&([#\w]+);/g,function(_,n){n=n.toLowerCase();if(n==="colon")return":";if(n.charAt(0)==="#"){return n.charAt(1)==="x"?String.fromCharCode(parseInt(n.substring(2),16)):String.fromCharCode(+n.substring(1))}return""})}function replace(regex,opt){regex=regex.source;opt=opt||"";return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,"$1");regex=regex.replace(name,val);return self}}function noop(){}noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key]}}}return obj}function marked(src,opt,callback){if(callback||typeof opt==="function"){if(!callback){callback=opt;opt=null}opt=merge({},marked.defaults,opt||{});var highlight=opt.highlight,tokens,pending,i=0;try{tokens=Lexer.lex(src,opt)}catch(e){return callback(e)}pending=tokens.length;var done=function(err){if(err){opt.highlight=highlight;return callback(err)}var out;try{out=Parser.parse(tokens,opt)}catch(e){err=e}opt.highlight=highlight;return err?callback(err):callback(null,out)};if(!highlight||highlight.length<3){return done()}delete opt.highlight;if(!pending)return done();for(;i<tokens.length;i++){(function(token){if(token.type!=="code"){return--pending||done()}return highlight(token.text,token.lang,function(err,code){if(err)return done(err);if(code==null||code===token.text){return--pending||done()}token.text=code;token.escaped=true;--pending||done()})})(tokens[i])}return}try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt)}catch(e){e.message+="\nPlease report this to https://github.com/chjj/marked.";if((opt||marked.defaults).silent){return"<p>An error occurred:</p><pre>"+escape(e.message+"",true)+"</pre>"}throw e}}marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,sanitizer:null,mangle:true,smartLists:false,silent:false,highlight:null,langPrefix:"lang-",smartypants:false,headerPrefix:"",renderer:new Renderer,xhtml:false};marked.Parser=Parser;marked.parser=Parser.parse;marked.Renderer=Renderer;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof module!=="undefined"&&typeof exports==="object"){module.exports=marked}else if(typeof define==="function"&&define.amd){define(function(){return marked})}else{this.marked=marked}}).call(function(){return this||(typeof window!=="undefined"?window:global)}());
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/custom.css b/examples/webengine/recipebrowser/resources/pages/assets/custom.css
new file mode 100644
index 000000000..9ddc19466
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/assets/custom.css
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+body {
+ padding-top: 0;
+ margin-top: 0;
+}
+
+#content {
+ display: none;
+}
+
+img {
+ width: 100%;
+ height: 100%;
+}
+
+li {
+ margin-left: 25px;
+}
+
+ol li {
+ margin-bottom: 10px;
+}
+
+* {
+ max-width: 960px !important;
+}
diff --git a/examples/webengine/recipebrowser/resources/pages/assets/custom.js b/examples/webengine/recipebrowser/resources/pages/assets/custom.js
new file mode 100644
index 000000000..aaa22a290
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/assets/custom.js
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+marked.setOptions({
+ renderer: new marked.Renderer(),
+ gfm: true,
+ tables: true,
+ breaks: false,
+ pedantic: false,
+ sanitize: false,
+ smartLists: true,
+ smartypants: false
+});
+
+// Poor man document.ready();
+(function() {
+ var placeholder = document.getElementById('placeholder');
+ var content = document.getElementById('content');
+ placeholder.innerHTML = marked(content.innerHTML);
+})();
diff --git a/examples/webengine/recipebrowser/resources/pages/burger.html b/examples/webengine/recipebrowser/resources/pages/burger.html
new file mode 100644
index 000000000..315c0a866
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/burger.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Insanity Burger</title>
+ <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="assets/custom.css">
+</head>
+<body>
+ <div id="placeholder"></div>
+ <div id="content">
+
+<img src="images/burger.jpg" alt="Insanity Burger" title="Insanity Burger" />
+Insanity burger
+===============
+
+### Ingredients
+
+* 800 g minced chuck steak
+* olive oil
+* 1 large red onion
+* 1 splash of white wine vinegar
+* 2 large gherkins
+* 4 sesame-topped brioche burger buns
+* 4-8 rashers of smoked streaky bacon
+* 4 teaspoons American mustard
+* Tabasco Chipotle sauce
+* 4 thin slices of Red Leicester cheese
+* 4 teaspoons tomato ketchup
+
+#### For the burger sauce
+* ¼ of an iceberg lettuce
+* 2 heaped tablespoons mayonnaise
+* 1 heaped tablespoon tomato ketchup
+* 1 teaspoon Tabasco Chipotle sauce
+* 1 teaspoon Worcestershire sauce
+* 1 teaspoon brandy, or bourbon (optional)
+
+### Instructions
+For the best burger, go to your butcher’s and ask them to mince 800g of chuck steak for you.
+This cut has a really good balance of fat and flavoursome meat. Divide it into 4 and, with wet
+hands, roll each piece into a ball, then press into flat patties roughly 12cm wide and about 2cm
+wider than your buns. Place on an oiled plate and chill in the fridge. Next, finely slice the red
+onion, then dress in a bowl with the vinegar and a pinch of sea salt. Slice the gherkins and halve
+the buns. Finely chop the lettuce and mix with the rest of the burger sauce ingredients in a bowl,
+then season to taste.
+
+I like to only cook 2 burgers at a time to achieve perfection, so get two pans on the go – a large
+non-stick pan on a high heat for your burgers and another on a medium heat for the bacon. Pat your
+burgers with oil and season them with salt and pepper. Put 2 burgers into the first pan, pressing
+down on them with a fish slice, then put half the bacon into the other pan. After 1 minute, flip
+the burgers and brush each cooked side with ½ a teaspoon of mustard and a dash of Tabasco. After
+another minute, flip onto the mustard side and brush again with another ½ teaspoon of mustard and
+a second dash of Tabasco on the other side. Cook for one more minute, by which point you can place
+some crispy bacon on top of each burger with a slice of cheese. Add a tiny splash of water to the
+pan and place a heatproof bowl over the burgers to melt the cheese – 30 seconds should do it. At the
+same time, toast 2 split buns in the bacon fat in the other pan until lightly golden. Repeat with
+the remaining two burgers.
+
+To build each burger, add a quarter of the burger sauce to the bun base, then top with a cheesy
+bacon burger, a quarter of the onions and gherkins. Rub the bun top with a teaspoon of ketchup,
+then gently press together. As the burger rests, juices will soak into the bun, so serve right
+away, which is great, or for an extra filthy experience, wrap each one in greaseproof paper, then
+give it a minute to go gorgeous and sloppy.
+
+**Enjoy!**
+
+ </div><!--End of content-->
+
+ <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/custom.js"></script>
+</body>
+</html>
+
+
+
diff --git a/examples/webengine/recipebrowser/resources/pages/cupcakes.html b/examples/webengine/recipebrowser/resources/pages/cupcakes.html
new file mode 100644
index 000000000..c169196f2
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/cupcakes.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Cupcakes</title>
+ <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="assets/custom.css">
+</head>
+<body>
+ <div id="placeholder"></div>
+ <div id="content">
+
+<img src="images/cupcakes.jpg" alt="Cupcakes" title="Cupcakes" />
+Cupcakes
+=============
+
+### Ingredients
+
+* 300 g caster sugar
+* 150 ml sunflower oil
+* 1 teaspoon vanilla extract
+* 500 g dairy-free soya yoghurt
+* 2 teaspoons cider vinegar
+* 350 g plain flour
+* 1 teaspoon bicarbonate of soda
+* 1½ teaspoons baking powder
+
+#### For the vegan vanilla icing
+* 200 g dairy-free soya spread , chilled
+* 660 g icing sugar
+* ½ teaspoon vanilla extract
+
+### Instructions
+1. Preheat the oven to 170°C fan/375°F/gas 5.
+2. Place the sugar, oil and vanilla extract in a large bowl, then beat with an electric mixer for 1 to 2 minutes, until well combined.
+3. Mix the yoghurt and vinegar together in a bowl, then add to the mixture and beat for 1 to 2 minutes.
+4. Add the remaining cupcake ingredients and 1 teaspoon of fine sea salt, then whisk until smooth and just combined.
+5. Fill the paper cases two-thirds full with mixture, but don’t bother to smooth it out.
+6. Bake for 20 minutes, or until they spring back when touched. Leave to cool, transferring to a wire cooling rack after 5 minutes.
+7. Meanwhile, make the icing. Beat the soya spread with an electric mixer for 1 to 2 minutes, or until smooth.
+8. Sift the icing sugar into a large bowl, then add to the soya spread in two stages, beating well between each.
+9. Add the vanilla extract and a small splash of water, then whisk for a further few minutes, or until silky smooth – if it’s too stiff, add a splash more water to loosen.
+10. Once the cupcakes are cool, decorate them with the icing and add a few sprinkles too if you like – whatever takes your fancy – then enjoy.
+
+**Enjoy!**
+
+ </div><!--End of content-->
+ <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/custom.js"></script>
+</body>
+</html>
+
+
+
diff --git a/examples/webengine/recipebrowser/resources/pages/images/burger.jpg b/examples/webengine/recipebrowser/resources/pages/images/burger.jpg
new file mode 100644
index 000000000..edc0c65de
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/images/burger.jpg
Binary files differ
diff --git a/examples/webengine/recipebrowser/resources/pages/images/cupcakes.jpg b/examples/webengine/recipebrowser/resources/pages/images/cupcakes.jpg
new file mode 100644
index 000000000..cce52ba23
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/images/cupcakes.jpg
Binary files differ
diff --git a/examples/webengine/recipebrowser/resources/pages/images/pasta.jpg b/examples/webengine/recipebrowser/resources/pages/images/pasta.jpg
new file mode 100644
index 000000000..7ac924b79
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/images/pasta.jpg
Binary files differ
diff --git a/examples/webengine/recipebrowser/resources/pages/images/pizza.jpg b/examples/webengine/recipebrowser/resources/pages/images/pizza.jpg
new file mode 100644
index 000000000..8d8f756af
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/images/pizza.jpg
Binary files differ
diff --git a/examples/webengine/recipebrowser/resources/pages/images/skewers.jpg b/examples/webengine/recipebrowser/resources/pages/images/skewers.jpg
new file mode 100644
index 000000000..6bb2f1172
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/images/skewers.jpg
Binary files differ
diff --git a/examples/webengine/recipebrowser/resources/pages/images/soup.jpg b/examples/webengine/recipebrowser/resources/pages/images/soup.jpg
new file mode 100644
index 000000000..fc9dff906
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/images/soup.jpg
Binary files differ
diff --git a/examples/webengine/recipebrowser/resources/pages/images/steak.jpg b/examples/webengine/recipebrowser/resources/pages/images/steak.jpg
new file mode 100644
index 000000000..240b72eb4
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/images/steak.jpg
Binary files differ
diff --git a/examples/webengine/recipebrowser/resources/pages/pasta.html b/examples/webengine/recipebrowser/resources/pages/pasta.html
new file mode 100644
index 000000000..c94b0df0a
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/pasta.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Pasta</title>
+ <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="assets/custom.css">
+</head>
+<body>
+ <div id="placeholder"></div>
+ <div id="content">
+
+<img src="images/pasta.jpg" alt="Pasta" title="Pasta" />
+Pasta
+=============
+
+### Ingredients
+
+* 2 red peppers , deseeded and sliced
+* 2 yellow peppers , deseeded and sliced
+* extra virgin olive oil
+* sea salt
+* freshly ground black pepper
+* 2 red onions , peeled and finely sliced
+* 2 cloves garlic , peeled and grated
+* 2 handfuls fresh flat-leaf parsley , leaves finely chopped, stalks reserved
+* 2 tablespoons red wine vinegar or balsamic vinegar
+* 2 handfuls Parmesan cheese , grated
+* 2 heaped tablespoons mascarpone cheese or crème fraîche , optional
+* 455 g rigatoni, penne or spaghetti
+
+
+### Instructions
+1. Put all the peppers in a large frying pan over a medium heat with a little olive oil and a pinch of salt and pepper.
+2. Place a lid on, and cook slowly for 15 minutes until softened. Don't rush this too much, as cooking the peppers slowly like this really helps to bring out the flavour.
+3. Add the onion and cook for a further 20 minutes.
+4. Then add the garlic and parsley stalks and toss around, keeping everything moving in the pan.
+5. Cook for about 3 minutes most. Have a little taste, and season with a bit more salt and pepper.
+5. Add the vinegar - it will sizzle away, so give everything a good toss.
+6. Then add one handful of the grated Parmesan and the mascarpone or crème fraîche if you are using it and turn the heat down to minimum while you cook the pasta.
+7. Meanwhile put a large pot of salted water on to boil.
+8. Add the pasta to the boiling water and cook according to the packet instructions.
+9. When cooked, drain in a colander, reserving some of the cooking water.
+10. Put the peppers, pasta and parsley leaves into a large warmed bowl.
+11. Give them a good toss together, then add a little of the pasta cooking water and a few good lugs of extra virgin olive oil to coat the pasta nicely.
+12. Serve straight away sprinkled with the rest of the Parmesan.
+
+**Enjoy!**
+
+ </div><!--End of content-->
+ <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/custom.js"></script>
+</body>
+</html>
+
+
+
diff --git a/examples/webengine/recipebrowser/resources/pages/pizza.html b/examples/webengine/recipebrowser/resources/pages/pizza.html
new file mode 100644
index 000000000..a1ebfa18e
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/pizza.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Pizza Diavola</title>
+ <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="assets/custom.css">
+</head>
+<body>
+ <div id="placeholder"></div>
+ <div id="content">
+
+<img src="images/pizza.jpg" alt="Pizza Diavola" title="Pizza Diavola" />
+Pizza Diavola
+=============
+
+### Ingredients
+
+* 2 pizza dough balls
+* 100g Mozzarella
+* 400g Passata
+* 200 g Spicy Salami
+* 2 fresh chillies
+* Extra virgin olive oil
+* Salt
+
+### Instructions
+1. Preheat oven to 210 oc.
+2. Get your pizza dough balls ( depending on how many you are making) and roll them out to about 12 inches diameter using your hands in a circular stretching technique or using a rolling pin.
+3. With the dough prepared now get our sauce ready by mixing the passata with three tbsp of the olive oil and a good pinch of salt.
+4. Now slice up your salami into thin-ish slices and also finely chop the fresh chillies.
+5. Next, slice or dice your mozzarella and we are ready to dress the pizza.
+6. Add half the tomato sauce to each base and spread evenly leaving a half inch perimeter.
+7. Add the mozzarella, salami and finish with the chillies.
+8. Finally drizzle with some more olive oil and your are ready to cook your pizza diavola.
+9. Place in the oven for ten minutes or until golden.
+10. Remove from the oven, slice, and enjoy your pizza diavola.
+
+**Enjoy!**
+
+ </div><!--End of content-->
+ <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/custom.js"></script>
+</body>
+</html>
+
+
+
diff --git a/examples/webengine/recipebrowser/resources/pages/skewers.html b/examples/webengine/recipebrowser/resources/pages/skewers.html
new file mode 100644
index 000000000..63d85f7e1
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/skewers.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Grilled skewers</title>
+ <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="assets/custom.css">
+</head>
+<body>
+ <div id="placeholder"></div>
+ <div id="content">
+
+<img src="images/skewers.jpg" alt="Grilled skewers" title="Grilled skewers" />
+Grilled skewers
+======================
+
+### Ingredients
+
+* 3 cloves of garlic
+* 200g kefalotyri cheese
+* 2 medium aubergine
+* 1 iceberg lettuce
+* 1 tablespoon coriander seeds
+* 2 teaspoons dried oregano
+* 2 lemons
+* 4 tablespoons olive oil
+* 600g lamb neck fillet , in 2cm chunks
+* 12 fresh bay leaves
+
+### Instructions
+1. Peel and crush the garlic.
+2. Chop the cheese into bite-sized pieces, trim and chop the aubergines into 2cm chunks, and trim and finely slice the lettuce.
+3. Finely crush the coriander seeds in a pestle and mortar and add to a large bowl with the oregano and garlic. Finely grate in the lemon zest (reserve the zested lemons) and stir in the oil.
+4. Season, then add the cheese, lamb, aubergines and bay leaves. Leave to marinate for at least an hour, or overnight if you can.
+5. Meanwhile, pickle your cabbage. Trim, core and finely slice the cabbage, then place in a colander in the sink or over a bowl and toss with 2 teaspoons of sea salt. Cover and set aside for at least 2 hours, then rinse.
+6. Peel and finely slice the onions, then transfer to a bowl along with the cabbage.
+7. Put the remaining ingredients in a pan and bring to a boil. Simmer for 10 minutes, then pour over the cabbage and onions. Transfer to sterilised jars – this will keep for up to 1 month.
+8. For the flatbreads, put the flour, baking powder, buttermilk and half of the sesame seeds in a bowl and mix until everything is combined.
+9. Tip onto a lightly floured surface and knead briefly. Divide into six, using a rolling pin to roll them into 1 to 2mm rounds.
+10. Scatter with the remaining sesame seeds and run the rolling pin over them. Pop the flatbreads onto the hot barbecue for 1 to 2 minutes on each side.
+11. Load 12 skewers with the cheese, lamb, aubergines and bay leaves, then place on the barbecue (not directly over the coals) for 20 to 25 minutes, turning often, until the lamb is medium-rare and the aubergines are cooked.
+12. Serve the lamb with the flatbreads, cabbage, lettuce and lemon wedges.
+
+**Enjoy!**
+
+ </div><!--End of content-->
+
+ <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/custom.js"></script>
+</body>
+</html>
+
+
+
diff --git a/examples/webengine/recipebrowser/resources/pages/soup.html b/examples/webengine/recipebrowser/resources/pages/soup.html
new file mode 100644
index 000000000..c7537d94c
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/soup.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Soup</title>
+ <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="assets/custom.css">
+</head>
+<body>
+ <div id="placeholder"></div>
+ <div id="content">
+
+<img src="images/soup.jpg" alt="Soup" title="Soup" />
+Soup
+=============
+
+### Ingredients
+
+* 2 potatoes
+* 2 onions
+* 2 cloves of garlic
+* olive oil
+* 400 ml organic stock
+* 3 bunches of watercress
+
+### Instructions
+* Peel and roughly chop the potatoes, onions and garlic.
+* In a large saucepan, heat a little olive oil, then sauté the potato, onion and garlic until the onions are translucent.
+* Add the stock and simmer until the potato is soft. Chop and add the watercress and simmer for a further 3 to 4 minutes.
+* Using a hand blender, liquidise the soup until smooth.
+* Serve with a swirl of crème fraîche and some Fortt’s Bath Oliver biscuits, if you like.
+
+**Enjoy!**
+
+ </div><!--End of content-->
+ <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/custom.js"></script>
+</body>
+</html>
+
+
+
diff --git a/examples/webengine/recipebrowser/resources/pages/steak.html b/examples/webengine/recipebrowser/resources/pages/steak.html
new file mode 100644
index 000000000..1871f0fe8
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/pages/steak.html
@@ -0,0 +1,68 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title>Grilled steak and rice</title>
+ <link rel="stylesheet" type="text/css" href="assets/3rdparty/markdown.css">
+ <link rel="stylesheet" type="text/css" href="assets/custom.css">
+</head>
+<body>
+ <div id="placeholder"></div>
+ <div id="content">
+
+<img src="images/steak.jpg" alt="Grilled steak and rice" title="Grilled steak and rice" />
+Grilled steak and rice
+======================
+
+### Ingredients
+
+#### For the ratatouille
+* courgette
+* 1 small aubergine
+* 2 mixed-color peppers
+* 1 red onion
+* 1 heaped teaspoon harissa
+* 2 anchovy fillets
+* 2-4 cloves of garlic
+* 700 g passata
+* 1 tablespoon balsamic vinegar
+* ½ bunch fresh basil
+* 2 tablespoons fat-free natural yoghurt
+
+#### For the rice
+* 1 mug (300g) 10-minute wholegrain or basmati rice
+* 1 good pinch saffron
+* ½ lemon
+
+#### For the steak
+* 2 x 250 g quality sirloin steaks, fat removed
+* 1 teaspoon sweet paprika olive oil
+* ½ bunch fresh flat-leaf parsley
+* 1 heaped teaspoon Dijon mustard
+* 1 tablespoon extra virgin olive oil
+* ½ lemon
+
+### Instructions
+1. Halve the courgette lengthways, slice the aubergine 1cm thick and place both on the griddle pan, turning when charred.
+2. Put 1 mug of rice, 2 mugs of boiling water, the saffron, lemon half and a pinch of salt into the small pan, cover and cook until fluffy, stirring occasionally.
+3. Tear the seeds and stalks out of the peppers, then roughly chop with the peeled red onion and put into the casserole pan with the harissa, anchovies and 1 teaspoon of their oil.
+4. Squash in the unpeeled garlic through a garlic crusher and stir regularly.
+5. Remove the charred courgette and aubergine from the griddle pan, leaving it on the heat, and roughly chop them on a board.
+6. Add them to the casserole pan along with the passata and vinegar, and boil with the lid on.
+7. Rub the steaks with salt, the paprika and 1 teaspoon of olive oil and place on the hot griddle pan, turning every minute until cooked to your liking.
+8. On a board, finely slice the parsley stalks and roughly chop the leaves.
+9. Add the mustard and extra virgin olive oil, season with salt and pepper and squeeze over the lemon juice, then mix together and spread over the board.
+10. When the steaks are done, transfer them to the board, turn in the dressing, then slice.
+11. Tear the top leafy half of the basil into the ratatouille, season to taste, and serve with yoghurt and saffron rice.
+
+**Enjoy!**
+
+ </div><!--End of content-->
+
+ <script src="assets/3rdparty/marked.min.js"></script>
+ <script src="assets/custom.js"></script>
+</body>
+</html>
+
+
+
diff --git a/examples/webengine/recipebrowser/resources/qml/RecipeList.qml b/examples/webengine/recipebrowser/resources/qml/RecipeList.qml
new file mode 100644
index 000000000..c2432631e
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/qml/RecipeList.qml
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Controls 2.0
+import QtQuick.Controls.Material 2.0
+import QtQuick.Layouts 1.0
+
+FocusScope {
+ id: root
+ signal recipeSelected(url url)
+
+ ColumnLayout {
+ spacing: 0
+ anchors.fill: parent
+
+ ToolBar {
+ id: headerBackground
+ Layout.fillWidth: true
+ implicitHeight: headerText.height + 20
+
+ Label {
+ id: headerText
+ width: parent.width
+ text: qsTr("Favorite recipes")
+ padding: 10
+ anchors.centerIn: parent
+ }
+ }
+
+ ListView {
+ id: listView
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ keyNavigationWraps: true
+ clip: true
+ focus: true
+ ScrollBar.vertical: ScrollBar { }
+
+ model: recipeModel
+
+ delegate: ItemDelegate {
+ width: parent.width
+ text: model.name
+ contentItem: Text {
+ text: parent.text
+ font: parent.font
+ color: parent.enabled ? parent.Material.primaryTextColor
+ : parent.Material.hintTextColor
+ elide: Text.ElideRight
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ wrapMode: Text.Wrap
+ }
+
+ property url url: model.url
+ highlighted: ListView.isCurrentItem
+
+ onClicked: {
+ listView.forceActiveFocus()
+ listView.currentIndex = model.index
+ }
+ }
+
+ onCurrentItemChanged: {
+ root.recipeSelected(currentItem.url)
+ }
+
+ ListModel {
+ id: recipeModel
+
+ ListElement {
+ name: "Pizza Diavola"
+ url: "qrc:///pages/pizza.html"
+ }
+ ListElement {
+ name: "Steak"
+ url: "qrc:///pages/steak.html"
+ }
+ ListElement {
+ name: "Burger"
+ url: "qrc:///pages/burger.html"
+ }
+ ListElement {
+ name: "Soup"
+ url: "qrc:///pages/soup.html"
+ }
+ ListElement {
+ name: "Pasta"
+ url: "qrc:///pages/pasta.html"
+ }
+ ListElement {
+ name: "Grilled Skewers"
+ url: "qrc:///pages/skewers.html"
+ }
+ ListElement {
+ name: "Cupcakes"
+ url: "qrc:///pages/cupcakes.html"
+ }
+ }
+
+ ToolTip {
+ id: help
+ implicitWidth: root.width - padding * 3
+ y: root.y + root.height
+ delay: 1000
+ timeout: 5000
+ text: qsTr("Use keyboard, mouse, or touch controls to navigate through the\
+ recipes.")
+
+ contentItem: Text {
+ text: help.text
+ font: help.font
+ color: help.Material.primaryTextColor
+ wrapMode: Text.Wrap
+ }
+ }
+ }
+ }
+
+ function showHelp() {
+ help.open()
+ }
+}
+
diff --git a/examples/webengine/recipebrowser/resources/qml/main.qml b/examples/webengine/recipebrowser/resources/qml/main.qml
new file mode 100644
index 000000000..84067e8f5
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/qml/main.qml
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQml 2.0
+import QtQuick 2.0
+import QtQuick.Controls 2.0
+import QtQuick.Controls.Material 2.0
+import QtQuick.Layouts 1.0
+import QtQuick.Window 2.0
+import QtWebEngine 1.4
+
+ApplicationWindow {
+ id: appWindow
+ title: qsTr("Recipe Browser")
+ visible: true
+
+ property int shorterDesktop: 768
+ property int longerDesktop: 1024
+ property int shorterMin: 360
+ property int longerMin: 480
+ property bool isPortrait: Screen.primaryOrientation === Qt.PortraitOrientation
+ width: {
+ if (isEmbedded)
+ return Screen.width
+ var potentialWidth = shorterDesktop
+ if (!isPortrait)
+ potentialWidth = longerDesktop
+ return potentialWidth > Screen.width ? Screen.width : potentialWidth
+ }
+ height: {
+ if (isEmbedded)
+ return Screen.height
+ var potentialHeight = longerDesktop
+ if (!isPortrait)
+ potentialHeight = shorterDesktop
+ return potentialHeight > Screen.height ? Screen.height : potentialHeight
+ }
+ minimumWidth: isPortrait ? shorterMin : longerMin
+ minimumHeight: isPortrait ? longerMin : shorterMin
+
+ RowLayout {
+ id: container
+ anchors.fill: parent
+ spacing: 0
+
+ RecipeList {
+ id: recipeList
+ Layout.minimumWidth: 124
+ Layout.preferredWidth: parent.width / 3
+ Layout.maximumWidth: 300
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ focus: true
+ KeyNavigation.tab: webView
+ onRecipeSelected: webView.showRecipe(url)
+ }
+
+ WebEngineView {
+ id: webView
+ Layout.preferredWidth: 2 * parent.width / 3
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ KeyNavigation.tab: recipeList
+ KeyNavigation.priority: KeyNavigation.BeforeItem
+ // Make sure focus is not taken by the web view, so user can continue navigating
+ // recipes with the keyboard.
+ settings.focusOnNavigationEnabled: false
+ property bool firstLoadComplete: false
+ onLoadingChanged: {
+ if (loadRequest.status === WebEngineView.LoadSucceededStatus
+ && !firstLoadComplete) {
+ // Debounce the showing of the web content, so images are more likely
+ // to have loaded completely.
+ showTimer.start()
+ }
+ }
+
+ Timer {
+ id: showTimer
+ interval: 500
+ repeat: false
+ onTriggered: {
+ webView.show(true)
+ webView.firstLoadComplete = true
+ recipeList.showHelp()
+ }
+ }
+
+ Rectangle {
+ id: webViewPlaceholder
+ anchors.fill: parent
+ z: 1
+ color: "white"
+
+ BusyIndicator {
+ id: busy
+ anchors.centerIn: parent
+ }
+ }
+
+ function showRecipe(url) {
+ webView.url = url
+ }
+
+ function show(show) {
+ if (show === true) {
+ busy.running = false
+ webViewPlaceholder.visible = false
+ } else {
+ webViewPlaceholder.visible = true
+ busy.running = true
+ }
+ }
+ }
+ }
+}
diff --git a/examples/webengine/recipebrowser/resources/resources.qrc b/examples/webengine/recipebrowser/resources/resources.qrc
new file mode 100644
index 000000000..ae5aa2ed3
--- /dev/null
+++ b/examples/webengine/recipebrowser/resources/resources.qrc
@@ -0,0 +1,28 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/main.qml</file>
+ <file>qml/RecipeList.qml</file>
+
+ <file>pages/pizza.html</file>
+ <file>pages/burger.html</file>
+ <file>pages/steak.html</file>
+ <file>pages/soup.html</file>
+ <file>pages/pasta.html</file>
+ <file>pages/skewers.html</file>
+ <file>pages/cupcakes.html</file>
+
+ <file>pages/assets/3rdparty/marked.min.js</file>
+ <file>pages/assets/3rdparty/default.md</file>
+ <file>pages/assets/3rdparty/markdown.css</file>
+ <file>pages/assets/custom.css</file>
+ <file>pages/assets/custom.js</file>
+
+ <file>pages/images/burger.jpg</file>
+ <file>pages/images/pizza.jpg</file>
+ <file>pages/images/steak.jpg</file>
+ <file>pages/images/soup.jpg</file>
+ <file>pages/images/pasta.jpg</file>
+ <file>pages/images/skewers.jpg</file>
+ <file>pages/images/cupcakes.jpg</file>
+ </qresource>
+</RCC>
diff --git a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp
index f044219ca..09f9a746b 100644
--- a/examples/webenginewidgets/demobrowser/browsermainwindow.cpp
+++ b/examples/webenginewidgets/demobrowser/browsermainwindow.cpp
@@ -109,6 +109,9 @@ BrowserMainWindow::BrowserMainWindow(QWidget *parent, Qt::WindowFlags flags)
, m_historyForward(0)
, m_stop(0)
, m_reload(0)
+#ifndef QT_NO_PRINTER
+ , m_currentPrinter(nullptr)
+#endif
{
setToolButtonStyle(Qt::ToolButtonFollowStyle);
setAttribute(Qt::WA_DeleteOnClose, true);
@@ -312,6 +315,8 @@ void BrowserMainWindow::setupMenu()
fileMenu->addSeparator();
#if defined(QWEBENGINEPAGE_PRINT)
fileMenu->addAction(tr("P&rint Preview..."), this, SLOT(slotFilePrintPreview()));
+#endif
+#ifndef QT_NO_PRINTER
fileMenu->addAction(tr("&Print..."), this, SLOT(slotFilePrint()), QKeySequence::Print);
#endif
fileMenu->addAction(tr("&Print to PDF..."), this, SLOT(slotFilePrintToPDF()));
@@ -403,7 +408,10 @@ void BrowserMainWindow::setupMenu()
viewMenu->addAction(tr("Reset &Zoom"), this, SLOT(slotViewResetZoom()), QKeySequence(Qt::CTRL | Qt::Key_0));
viewMenu->addSeparator();
- viewMenu->addAction(tr("Page S&ource"), this, SLOT(slotViewPageSource()), tr("Ctrl+Alt+U"));
+ QAction *m_pageSource = viewMenu->addAction(tr("Page S&ource"));
+ m_pageSource->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_U));
+ m_tabWidget->addWebAction(m_pageSource, QWebEnginePage::ViewSource);
+
QAction *a = viewMenu->addAction(tr("&Full Screen"), this, SLOT(slotViewFullScreen(bool)), Qt::Key_F11);
a->setCheckable(true);
@@ -710,10 +718,10 @@ void BrowserMainWindow::slotFilePrintPreview()
void BrowserMainWindow::slotFilePrint()
{
-#if defined(QWEBENGINEPAGE_PRINT)
+#ifndef QT_NO_PRINTER
if (!currentTab())
return;
- printRequested(currentTab()->page()->mainFrame());
+ printRequested(currentTab()->page());
#endif
}
@@ -747,16 +755,27 @@ void BrowserMainWindow::slotFilePrintToPDF()
currentTab()->page()->printToPdf(invoke(this, &BrowserMainWindow::slotHandlePdfPrinted), dialog->pageLayout());
}
-#if defined(QWEBENGINEPAGE_PRINT)
-void BrowserMainWindow::printRequested(QWebEngineFrame *frame)
+#ifndef QT_NO_PRINTER
+void BrowserMainWindow::slotHandlePagePrinted(bool result)
+{
+ delete m_currentPrinter;
+ m_currentPrinter = nullptr;
+}
+
+
+void BrowserMainWindow::printRequested(QWebEnginePage *page)
{
#ifndef QT_NO_PRINTDIALOG
- QPrinter printer;
- QPrintDialog *dialog = new QPrintDialog(&printer, this);
+ if (m_currentPrinter)
+ return;
+ m_currentPrinter = new QPrinter();
+ QPrintDialog *dialog = new QPrintDialog(m_currentPrinter, this);
dialog->setWindowTitle(tr("Print Document"));
- if (dialog->exec() != QDialog::Accepted)
+ if (dialog->exec() != QDialog::Accepted) {
+ slotHandlePagePrinted(false);
return;
- frame->print(&printer);
+ }
+ page->print(m_currentPrinter, invoke(this, &BrowserMainWindow::slotHandlePagePrinted));
#endif
}
#endif
@@ -867,20 +886,6 @@ void BrowserMainWindow::slotViewFullScreen(bool makeFullScreen)
}
}
-void BrowserMainWindow::slotViewPageSource()
-{
- if (!currentTab())
- return;
-
- QPlainTextEdit *view = new QPlainTextEdit;
- view->setWindowTitle(tr("Page Source of %1").arg(currentTab()->title()));
- view->setMinimumWidth(640);
- view->setAttribute(Qt::WA_DeleteOnClose);
- view->show();
-
- currentTab()->page()->toHtml(invoke(view, &QPlainTextEdit::setPlainText));
-}
-
void BrowserMainWindow::slotHome()
{
QSettings settings;
diff --git a/examples/webenginewidgets/demobrowser/browsermainwindow.h b/examples/webenginewidgets/demobrowser/browsermainwindow.h
index 9fb6b0851..91e1c1d2f 100644
--- a/examples/webenginewidgets/demobrowser/browsermainwindow.h
+++ b/examples/webenginewidgets/demobrowser/browsermainwindow.h
@@ -56,7 +56,10 @@
#include <QtCore/QUrl>
QT_BEGIN_NAMESPACE
-class QWebEngineFrame;
+#ifndef QT_NO_PRINTER
+class QPrinter;
+#endif
+class QWebEnginePage;
QT_END_NAMESPACE
class AutoSaver;
@@ -123,7 +126,6 @@ private slots:
void slotViewToolbar();
void slotViewBookmarksBar();
void slotViewStatusbar();
- void slotViewPageSource();
void slotViewFullScreen(bool enable);
void slotWebSearch();
@@ -140,8 +142,9 @@ private slots:
void slotSwapFocus();
void slotHandlePdfPrinted(const QByteArray&);
-#if defined(QWEBENGINEPAGE_PRINT)
- void printRequested(QWebEngineFrame *frame);
+#ifndef QT_NO_PRINTER
+ void slotHandlePagePrinted(bool result);
+ void printRequested(QWebEnginePage *page);
#endif
void geometryChangeRequested(const QRect &geometry);
void updateToolbarActionText(bool visible);
@@ -177,6 +180,10 @@ private:
QAction *m_restoreLastSession;
QAction *m_addBookmark;
+#ifndef QT_NO_PRINTER
+ QPrinter *m_currentPrinter;
+#endif
+
QIcon m_reloadIcon;
QIcon m_stopIcon;
diff --git a/examples/webenginewidgets/demobrowser/webview.cpp b/examples/webenginewidgets/demobrowser/webview.cpp
index a785ae48b..ab2a4f3c6 100644
--- a/examples/webenginewidgets/demobrowser/webview.cpp
+++ b/examples/webenginewidgets/demobrowser/webview.cpp
@@ -365,6 +365,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)
menu = new QMenu(this);
menu->addAction(page()->action(QWebEnginePage::OpenLinkInThisWindow));
menu->addAction(page()->action(QWebEnginePage::OpenLinkInNewWindow));
+ menu->addAction(page()->action(QWebEnginePage::OpenLinkInNewTab));
menu->addAction(page()->action(QWebEnginePage::OpenLinkInNewBackgroundTab));
menu->addSeparator();
menu->addAction(page()->action(QWebEnginePage::DownloadLinkToDisk));
@@ -392,11 +393,6 @@ void WebView::wheelEvent(QWheelEvent *event)
QWebEngineView::wheelEvent(event);
}
-void WebView::openLinkInNewTab()
-{
- pageAction(QWebEnginePage::OpenLinkInNewTab)->trigger();
-}
-
void WebView::onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature)
{
FeaturePermissionBar *permissionBar = new FeaturePermissionBar(this);
diff --git a/examples/webenginewidgets/demobrowser/webview.h b/examples/webenginewidgets/demobrowser/webview.h
index 8cb502fd1..7531254d6 100644
--- a/examples/webenginewidgets/demobrowser/webview.h
+++ b/examples/webenginewidgets/demobrowser/webview.h
@@ -115,7 +115,6 @@ private slots:
void setProgress(int progress);
void loadFinished(bool success);
void setStatusBarText(const QString &string);
- void openLinkInNewTab();
void onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature);
void onIconChanged(const QIcon &icon);
diff --git a/examples/webenginewidgets/spellchecker/data/icon.svg b/examples/webenginewidgets/spellchecker/data/icon.svg
new file mode 100644
index 000000000..b90ff26dd
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/data/icon.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="94px" height="94px" viewBox="0 0 94 94" enable-background="new 0 0 94 94" xml:space="preserve">
+<g>
+ <circle fill="none" cx="47" cy="47" r="47"/>
+ <g>
+ <path fill="#46A2DA" d="M47,92.979c-11.779,0-23.559-4.484-32.526-13.451C-3.461,61.591-3.461,32.409,14.472,14.474
+ C32.41-3.463,61.592-3.461,79.526,14.473c17.935,17.936,17.935,47.119,0.002,65.054l-0.002,0.001
+ C70.559,88.495,58.779,92.979,47,92.979z"/>
+ </g>
+ <path fill="#80C342" d="M93,47C93,21.595,72.405,1,47,1C34.297,1,22.797,6.149,14.473,14.473l65.054,65.054
+ C87.851,71.203,93,59.703,93,47z"/>
+ <g>
+ <path fill="#46A2DA" d="M47,65c-4.808,0-9.328-1.873-12.728-5.272c-7.018-7.019-7.018-18.438,0-25.456
+ C37.672,30.873,42.192,29,47,29s9.328,1.873,12.728,5.272c7.018,7.019,7.018,18.438,0,25.456C56.328,63.127,51.808,65,47,65z"/>
+ <path fill="#FFFFFF" d="M62.248,59.919c6.671-7.858,6.312-19.644-1.105-27.061C57.237,28.953,52.118,27,47,27
+ c-5.118,0-10.237,1.953-14.142,5.858c-7.81,7.81-7.81,20.474,0,28.284C36.763,65.047,41.882,67,47,67
+ c4.379,0,8.752-1.441,12.372-4.3L77.88,81.209c0.989-0.895,1.935-1.837,2.843-2.814L62.248,59.919z M35.686,58.314
+ c-6.238-6.238-6.238-16.389,0-22.627C38.708,32.664,42.726,31,47,31c4.274,0,8.292,1.664,11.314,4.686
+ c6.238,6.238,6.238,16.389,0,22.627C55.292,61.336,51.274,63,47,63C42.726,63,38.708,61.336,35.686,58.314z"/>
+ </g>
+</g>
+</svg>
diff --git a/examples/webenginewidgets/spellchecker/data/index.html b/examples/webenginewidgets/spellchecker/data/index.html
new file mode 100644
index 000000000..b6cec5fe0
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/data/index.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Contact us</title>
+ <link rel="stylesheet" type="text/css" href="style.css">
+ </head>
+ <body>
+ <form class="form">
+ <img class="logo" src="icon.svg" alt="qtwebengine">
+ <div class="header">
+ <h1>Contact us</h1>
+ <h2>We are here to help</h2>
+ </div>
+ <label>
+ <span>First Name:</span><input id="firstname" type="text" name="name" />
+ </label>
+ <label>
+ <span>Last Name:</span><input id="lastName" type="text" name="name" />
+ </label>
+ <label>
+ <span>Email Address:</span><input id="email" type="text" name="email" />
+ </label>
+ <label>
+ <span>Subject:</span><input id="subject" type="text" name="subject" />
+ </label>
+ <label>
+ <span>Message:</span><textarea id="feedback" name="feedback"></textarea>
+ </label>
+ <input type="submit" value="Send" />
+ </form>
+ </body>
+</html>
diff --git a/examples/webenginewidgets/spellchecker/data/spellchecker.qrc b/examples/webenginewidgets/spellchecker/data/spellchecker.qrc
new file mode 100644
index 000000000..a9c76cc7e
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/data/spellchecker.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>index.html</file>
+ <file>style.css</file>
+ <file>icon.svg</file>
+ </qresource>
+</RCC>
diff --git a/examples/webenginewidgets/spellchecker/data/style.css b/examples/webenginewidgets/spellchecker/data/style.css
new file mode 100644
index 000000000..7b6736f1f
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/data/style.css
@@ -0,0 +1,90 @@
+.logo {
+ width: 50px;
+ height: 50px;
+ float: left;
+ margin: 20px 20px 0px 20px;
+ -webkit-animation:spin 8s linear infinite;
+}
+@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
+
+.header {
+ display: inline
+}
+
+.form {
+ width: 450px;
+ height: 600px;
+ background: -webkit-linear-gradient(bottom, #ddd, #fff);
+ border: 1px solid #999;
+ border-radius: 12px;
+ color: #46a;
+ font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif;
+ font-size: 14px;
+ font-style: italic;
+ font-weight: bold;
+ margin: auto;
+ padding: 10px;
+ position: relative;
+ line-height: 26px;
+ text-decoration: none;
+ -webkit-box-shadow: 0px 0px 5px #444;
+}
+
+h1 {
+ padding-left:40px;
+ color: #46a2da;
+}
+
+h2 {
+ color: #80c342;
+ font-size: 13px;
+ margin-top: -20px;
+}
+
+span {
+ margin-left: 20px;
+}
+
+input {
+ width: 400px;
+ display: block;
+ border: 1px solid #999;
+ height: 25px;
+ margin-left: 20px;
+ margin-bottom: 10px;
+ padding-left: 10px;
+ -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);
+}
+
+textarea {
+ width: 400px;
+ max-width: 400px;
+ height: 180px;
+ max-height: 400px;
+ display: block;
+ margin-left: 20px;
+ padding-left: 10px;
+ padding-right: 10px;
+ -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);
+}
+
+input:focus, textarea:focus {
+ outline:none;
+ border: 1px solid #46a2da;
+}
+
+input[type=submit] {
+ width: 100px;
+ left: 170px;
+ bottom: 10px;
+ background: #46a2da;
+ color: #fff;
+ height: 30px;
+ position: absolute;
+ border-radius: 14px;
+}
+
+input[type=submit]:hover {
+ background: #80c342;
+}
+
diff --git a/examples/webenginewidgets/spellchecker/dict/de/README.txt b/examples/webenginewidgets/spellchecker/dict/de/README.txt
new file mode 100644
index 000000000..f9c94e06d
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/dict/de/README.txt
@@ -0,0 +1,20 @@
+This is dummy german dictionary which knows only following words:
+
+* ich
+* du
+* er
+* sie
+* es
+* wir
+* ihr
+* sie
+* Sie
+* liebe
+* liebst
+* liebt
+* lieben
+* liebt
+* qt
+
+Also each of words above can start with 'q' for example
+* qich
diff --git a/examples/webenginewidgets/spellchecker/dict/de/de-DE.aff b/examples/webenginewidgets/spellchecker/dict/de/de-DE.aff
new file mode 100644
index 000000000..ff8185771
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/dict/de/de-DE.aff
@@ -0,0 +1,5 @@
+SET UTF-8
+TRY esianrtolcdugmphbyfvkwzqESIANRTOLCDUGMPHBYFVKWZQ
+
+PFX Q Y 1
+PFX Q 0 q .
diff --git a/examples/webenginewidgets/spellchecker/dict/de/de-DE.dic b/examples/webenginewidgets/spellchecker/dict/de/de-DE.dic
new file mode 100644
index 000000000..d10ae2600
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/dict/de/de-DE.dic
@@ -0,0 +1,14 @@
+15
+du/Q
+er/Q
+es/Q
+ich/Q
+ihr/Q
+liebe/Q
+lieben/Q
+liebst/Q
+liebt/Q
+qt/Q
+sie/Q
+Sie/Q
+wir/Q
diff --git a/examples/webenginewidgets/spellchecker/dict/en/README.txt b/examples/webenginewidgets/spellchecker/dict/en/README.txt
new file mode 100644
index 000000000..41b529292
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/dict/en/README.txt
@@ -0,0 +1,16 @@
+This is dummy english dictionary which knows only following words:
+
+* I
+* you
+* he
+* she
+* it
+* we
+* they
+* love
+* loves
+* qt
+
+Also each of words above can start with 'q' for example:
+
+* qI
diff --git a/examples/webenginewidgets/spellchecker/dict/en/en-US.aff b/examples/webenginewidgets/spellchecker/dict/en/en-US.aff
new file mode 100644
index 000000000..ff8185771
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/dict/en/en-US.aff
@@ -0,0 +1,5 @@
+SET UTF-8
+TRY esianrtolcdugmphbyfvkwzqESIANRTOLCDUGMPHBYFVKWZQ
+
+PFX Q Y 1
+PFX Q 0 q .
diff --git a/examples/webenginewidgets/spellchecker/dict/en/en-US.dic b/examples/webenginewidgets/spellchecker/dict/en/en-US.dic
new file mode 100644
index 000000000..3d4ecdfa4
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/dict/en/en-US.dic
@@ -0,0 +1,11 @@
+10
+he/Q
+I/Q
+it/Q
+love/Q
+loves/Q
+qt/Q
+she/Q
+they/Q
+we/Q
+you/Q
diff --git a/examples/webenginewidgets/spellchecker/doc/images/spellchecker-example.png b/examples/webenginewidgets/spellchecker/doc/images/spellchecker-example.png
new file mode 100644
index 000000000..cc4e74946
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/doc/images/spellchecker-example.png
Binary files differ
diff --git a/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc b/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc
new file mode 100644
index 000000000..d5b972b93
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: http://www.gnu.org/copyleft/fdl.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example webenginewidgets/spellchecker
+ \title WebEngine Widgets Spellchecker Example
+ \ingroup webengine-widgetexamples
+ \brief Integrates a spellchecker into a simple HTML form.
+
+ \image spellchecker-example.png
+
+ \e {Spellchecker} demonstrates how to integrate spellchecking support into
+ an HTML form that enables users to submit spellchecked messages.
+
+ \include examples-run.qdocinc
+
+ \section1 Dictionaries
+
+ To be able to check the spelling, we need to provide the spellchecker with
+ dictionaries. In this example, we want to support the English and German
+ languages.
+
+ The Qt WebEngine spellchecker supports dictionaries from the
+ \l{Hunspell project}, but they have to be compiled into a special binary
+ format. A Hunspell dictionary consists of two files:
+
+ \list
+
+ \li A \c .dic file that is a dictionary containing words for the
+ language
+ \li An \c .aff file that defines the meaning of special flags in the
+ dictionary
+ \endlist
+
+ These two files can be converted into the \c bdic format by using the
+ \c qwebengine_convert_dict tool that is shipped together with Qt.
+
+ In this example, we are going to compile en_US and de_DE dictionaries.
+ However, the real full dictionaries would take too much space for the
+ purposes of this example. Therefore, we have created two dummy dictionaries
+ that contain the following words and can be used to demonstrate the
+ conversion process:
+
+ \list
+ \li English dictionary: I, you, he, she, it, we, they, love, loves, qt
+ \li German dictionary: ich, du, er, sie, es, wir, ihr, sie, Sie, liebe,
+ liebst, liebt, lieben, liebt, qt
+ \endlist
+
+ Each word in a dictionary can be prefixed with \c q. For more information
+ about how to create \c dic and \c aff files, see the Hunspell dictionary
+ file format specification in the \l{Hunspell Project}.
+
+ When a specific spellchecking language is requested, Qt WebEngine will try
+ to load the already compiled matching \c .bdic file first from
+ \e qtwebengine_dictionaries directories relative to the executable,
+ then it will look in \c QT_INSTALL_PREFIX/qtwebengines_dictionaries.
+
+ We specify the QMAKE_EXTRA_COMPILERS parameter in the project file to add a
+ conversion step to the build process:
+
+ \quotefromfile webenginewidgets/spellchecker/spellchecker.pro
+ \skipto CONVERT_TOOL
+ \printuntil QMAKE_EXTRA_COMPILERS
+
+ To set up a dictionary, we run \c qwebengine_convert_dic passing the
+ file path of the dictionary \c dic and \c bdic files. The \c aff file and
+ optional \c delta file are also picked up by the \c convert process.
+ The output \c bdic file is placed into the \e qtwebengine_dictionaries local
+ directory, which the application binary will run from.
+
+ \section1 Setting the Spellchecker
+
+ The constructor of our class is trivial.
+
+ \quotefromfile webenginewidgets/spellchecker/webview.cpp
+ \skipto WebView::WebView
+ \printuntil }
+ We define simple mapping between our dictionary filenames and
+ the actual language display name. We will use that mapping to display names
+ of dictionaries in the context menu. Spellchecking is disabled by default.
+ Therefore we also enable spellchecker and set the \e English dictionary.
+ When Qt WebEngine's spellcheck service initializes, it will try to load the
+ \c bdict dictionaries and to check them for consistency.
+ Any errors are logged by using the qWarning() function.
+
+ \section1 Switching the Spellchecking Language
+
+ The current language used for spellchecking is defined per profile, and can
+ get set using the QWebEngineProfile::setSpellCheckLanguage method. When the
+ user clicks on an underlined misspelled word, the default context menu
+ displays up to four suggestions. Selecting one will replace the misspelled
+ word. We could reimplement a number of suggestions, by overriding
+ QWebEngineView::contextMenuEvent and using
+ QWebEngineContextMenuData::spellCheckerSuggestions, but we will demonstrate
+ how to add langague options in the context menu instead:
+
+ \quotefromfile webenginewidgets/spellchecker/webview.cpp
+ \skipto void WebView::contextMenuEvent
+ \printuntil menu->popup
+ \printline }
+
+ Above, we get the QWebEngineContextMenuData instance using the
+ QWebEnginePage::contextMenuData method. We use it to be notified when the
+ user clicks on an editable field and show the \uicontrol {Check Spelling}
+ item in the context menu. Moreover, if spellchecking is enabled, we also
+ add the \uicontrol {Select Language} submenu with the supported languages.
+ When an action is triggered, we set the language with the
+ QWebEngineProfile::setSpellCheckLanguage call.
+*/
diff --git a/examples/webenginewidgets/spellchecker/main.cpp b/examples/webenginewidgets/spellchecker/main.cpp
new file mode 100644
index 000000000..0d411f665
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/main.cpp
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "webview.h"
+#include <QApplication>
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ WebView view;
+ view.setUrl(QUrl(QStringLiteral("qrc:/index.html")));
+ view.resize(500, 640);
+ view.show();
+
+ return app.exec();
+}
diff --git a/examples/webenginewidgets/spellchecker/spellchecker.pro b/examples/webenginewidgets/spellchecker/spellchecker.pro
new file mode 100644
index 000000000..c7bee6584
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/spellchecker.pro
@@ -0,0 +1,43 @@
+TEMPLATE = app
+TARGET = spellchecker
+QT += webenginewidgets
+CONFIG += c++11
+
+HEADERS += \
+ webview.h
+
+SOURCES += \
+ main.cpp \
+ webview.cpp
+
+RESOURCES += \
+ data/spellchecker.qrc
+
+DISTFILES += \
+ dict/en/README.txt \
+ dict/en/en-US.dic \
+ dict/en/en-US.aff \
+ dict/de/README.txt \
+ dict/de/de-DE.dic \
+ dict/de/de-DE.aff
+
+target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/spellchecker
+INSTALLS += target
+
+qtPrepareTool(CONVERT_TOOL, qwebengine_convert_dict)
+
+debug_and_release {
+ CONFIG(debug, debug|release): DICTIONARIES_DIR = debug/qtwebengine_dictionaries
+ else: DICTIONARIES_DIR = release/qtwebengine_dictionaries
+} else {
+ DICTIONARIES_DIR = qtwebengine_dictionaries
+}
+
+dict.files = $$PWD/dict/en/en-US.dic $$PWD/dict/de/de-DE.dic
+dictoolbuild.input = dict.files
+dictoolbuild.output = $${DICTIONARIES_DIR}/${QMAKE_FILE_BASE}.bdic
+dictoolbuild.depends = ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.aff
+dictoolbuild.commands = $${CONVERT_TOOL} ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
+dictoolbuild.name = Build ${QMAKE_FILE_IN_BASE}
+dictoolbuild.CONFIG = no_link target_predeps
+QMAKE_EXTRA_COMPILERS += dictoolbuild
diff --git a/examples/webenginewidgets/spellchecker/webview.cpp b/examples/webenginewidgets/spellchecker/webview.cpp
new file mode 100644
index 000000000..6c73d88fa
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/webview.cpp
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "webview.h"
+#include <QContextMenuEvent>
+#include <QMenu>
+#include <QWebEngineProfile>
+#include <QWebEngineContextMenuData>
+
+WebView::WebView(QWidget *parent)
+ : QWebEngineView(parent)
+{
+ m_spellCheckLanguages["English"] = "en-US";
+ m_spellCheckLanguages["German"] = "de-DE";
+ QWebEngineProfile *profile = page()->profile();
+ profile->setSpellCheckEnabled(true);
+ profile->setSpellCheckLanguage("en-US");
+}
+
+void WebView::contextMenuEvent(QContextMenuEvent *event)
+{
+ const QWebEngineContextMenuData &data = page()->contextMenuData();
+ Q_ASSERT(data.isValid());
+
+ if (!data.isContentEditable()) {
+ QWebEngineView::contextMenuEvent(event);
+ return;
+ }
+
+ QWebEngineProfile *profile = page()->profile();
+ const QString &language = profile->spellCheckLanguage();
+ QMenu *menu = page()->createStandardContextMenu();
+ menu->addSeparator();
+
+ QAction *spellcheckAction = new QAction(tr("Check Spelling"));
+ spellcheckAction->setCheckable(true);
+ spellcheckAction->setChecked(profile->isSpellCheckEnabled());
+ connect(spellcheckAction, &QAction::toggled, this, [profile](bool toogled) {
+ profile->setSpellCheckEnabled(toogled);
+ });
+ menu->addAction(spellcheckAction);
+
+ if (profile->isSpellCheckEnabled()) {
+ QMenu *subMenu = menu->addMenu(tr("Select Language"));
+ foreach (const QString &str, m_spellCheckLanguages.keys()) {
+ QAction *action = subMenu->addAction(str);
+ action->setCheckable(true);
+ QString lang = m_spellCheckLanguages[str];
+ action->setChecked(language == lang);
+ connect(action, &QAction::triggered, this, [profile, lang](){
+ profile->setSpellCheckLanguage(lang);
+ });
+ }
+ }
+ connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater);
+ menu->popup(event->globalPos());
+}
+
+
diff --git a/examples/webenginewidgets/spellchecker/webview.h b/examples/webenginewidgets/spellchecker/webview.h
new file mode 100644
index 000000000..787d06a1a
--- /dev/null
+++ b/examples/webenginewidgets/spellchecker/webview.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef WEBVIEW_H
+#define WEBVIEW_H
+
+#include <QWebEngineView>
+
+class WebView : public QWebEngineView
+{
+ Q_OBJECT
+
+public:
+ WebView(QWidget *parent = nullptr);
+
+protected:
+ void contextMenuEvent(QContextMenuEvent *event) override;
+
+private:
+ QMap<QString,QString> m_spellCheckLanguages;
+};
+
+#endif
diff --git a/src/3rdparty b/src/3rdparty
-Subproject f2097bbd2fb2161122764f056b4af6a1260187f
+Subproject b4c72f26c1b72ae2fedf601c3f5b6708bdff22d
diff --git a/src/core/access_token_store_qt.cpp b/src/core/access_token_store_qt.cpp
index 6c4cbc610..5b8fe83f7 100644
--- a/src/core/access_token_store_qt.cpp
+++ b/src/core/access_token_store_qt.cpp
@@ -47,6 +47,7 @@
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
#include "browser_context_qt.h"
#include "browser_context_adapter.h"
@@ -67,7 +68,7 @@ AccessTokenStoreQt::~AccessTokenStoreQt()
{
}
-void AccessTokenStoreQt::LoadAccessTokens(const LoadAccessTokensCallbackType& callback)
+void AccessTokenStoreQt::LoadAccessTokens(const LoadAccessTokensCallback& callback)
{
BrowserThread::PostTaskAndReply(BrowserThread::UI, FROM_HERE
, base::Bind(&AccessTokenStoreQt::performWorkOnUIThread, this)
@@ -76,10 +77,10 @@ void AccessTokenStoreQt::LoadAccessTokens(const LoadAccessTokensCallbackType& ca
void AccessTokenStoreQt::performWorkOnUIThread()
{
- m_systemRequestContext = WebEngineContext::current()->defaultBrowserContext()->browserContext()->GetRequestContext();
+ m_systemRequestContext = content::BrowserContext::GetDefaultStoragePartition(WebEngineContext::current()->defaultBrowserContext()->browserContext())->GetURLRequestContext();
}
-void AccessTokenStoreQt::respondOnOriginatingThread(const LoadAccessTokensCallbackType& callback)
+void AccessTokenStoreQt::respondOnOriginatingThread(const LoadAccessTokensCallback& callback)
{
callback.Run(m_accessTokenSet, m_systemRequestContext);
m_systemRequestContext = 0;
diff --git a/src/core/access_token_store_qt.h b/src/core/access_token_store_qt.h
index 0f45fd3a0..973f304c0 100644
--- a/src/core/access_token_store_qt.h
+++ b/src/core/access_token_store_qt.h
@@ -58,16 +58,16 @@ public:
AccessTokenStoreQt();
~AccessTokenStoreQt();
- virtual void LoadAccessTokens(const LoadAccessTokensCallbackType& request) Q_DECL_OVERRIDE;
+ virtual void LoadAccessTokens(const LoadAccessTokensCallback& request) Q_DECL_OVERRIDE;
virtual void SaveAccessToken(const GURL& serverUrl, const base::string16& accessToken) Q_DECL_OVERRIDE;
private:
void performWorkOnUIThread();
- void respondOnOriginatingThread(const LoadAccessTokensCallbackType& callback);
+ void respondOnOriginatingThread(const LoadAccessTokensCallback& callback);
net::URLRequestContextGetter *m_systemRequestContext;
- AccessTokenSet m_accessTokenSet;
+ AccessTokenMap m_accessTokenSet;
DISALLOW_COPY_AND_ASSIGN(AccessTokenStoreQt);
};
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 6e2d606b2..cb9d33087 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -15,9 +15,9 @@ CONFIG -= create_prl
# Copy this logic from qt_module.prf so that the intermediate library can be
# created to the same rules as the final module linking in core_module.pro.
!host_build:if(win32|mac):!macx-xcode {
- contains(QT_CONFIG, simulator_and_device): CONFIG += simulator_and_device
- contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release
- contains(QT_CONFIG, build_all):CONFIG += build_all
+ qtConfig(simulator_and_device): CONFIG += simulator_and_device
+ qtConfig(debug_and_release): CONFIG += debug_and_release
+ qtConfig(build_all): CONFIG += build_all
}
DEFINES += \
diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp
index bd3c5e7d9..730786bbd 100644
--- a/src/core/browser_accessibility_manager_qt.cpp
+++ b/src/core/browser_accessibility_manager_qt.cpp
@@ -82,8 +82,9 @@ QAccessibleInterface *BrowserAccessibilityManagerQt::rootParentAccessible()
return QAccessible::queryAccessibleInterface(m_parentObject);
}
-void BrowserAccessibilityManagerQt::NotifyAccessibilityEvent(ui::AXEvent event_type,
- BrowserAccessibility* node)
+void BrowserAccessibilityManagerQt::NotifyAccessibilityEvent(BrowserAccessibilityEvent::Source source,
+ ui::AXEvent event_type,
+ BrowserAccessibility* node)
{
BrowserAccessibilityQt *iface = static_cast<BrowserAccessibilityQt*>(node);
diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h
index 4ff9fb699..da50de9cb 100644
--- a/src/core/browser_accessibility_manager_qt.h
+++ b/src/core/browser_accessibility_manager_qt.h
@@ -59,15 +59,14 @@ public:
class BrowserAccessibilityManagerQt : public BrowserAccessibilityManager
{
public:
- BrowserAccessibilityManagerQt(
- QObject* parentObject,
- const ui::AXTreeUpdate& initialTree,
- BrowserAccessibilityDelegate* delegate,
- BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactoryQt());
+ BrowserAccessibilityManagerQt(QObject* parentObject,
+ const ui::AXTreeUpdate& initialTree,
+ BrowserAccessibilityDelegate* delegate,
+ BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactoryQt());
- void NotifyAccessibilityEvent(
- ui::AXEvent event_type,
- BrowserAccessibility* node) Q_DECL_OVERRIDE;
+ void NotifyAccessibilityEvent(BrowserAccessibilityEvent::Source source,
+ ui::AXEvent event_type,
+ BrowserAccessibility* node) Q_DECL_OVERRIDE;
QAccessibleInterface *rootParentAccessible();
diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp
index fecbac111..30e6efc2e 100644
--- a/src/core/browser_accessibility_qt.cpp
+++ b/src/core/browser_accessibility_qt.cpp
@@ -418,7 +418,7 @@ QAccessible::State BrowserAccessibilityQt::state() const
state.expanded = true;
if (s & (1 << ui::AX_STATE_FOCUSABLE))
state.focusable = true;
- if (s & (1 << ui::AX_STATE_FOCUSED))
+ if (manager()->GetFocus() == this)
state.focused = true;
if (s & (1 << ui::AX_STATE_HASPOPUP))
state.hasPopup = true;
@@ -480,7 +480,7 @@ QStringList BrowserAccessibilityQt::actionNames() const
void BrowserAccessibilityQt::doAction(const QString &actionName)
{
if (actionName == QAccessibleActionInterface::setFocusAction())
- manager()->SetFocus(this, true);
+ manager()->SetFocus(*this);
}
QStringList BrowserAccessibilityQt::keyBindingsForAction(const QString &actionName) const
diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp
index 24e2dc2c2..cf7987fa7 100644
--- a/src/core/browser_context_adapter.cpp
+++ b/src/core/browser_context_adapter.cpp
@@ -45,6 +45,7 @@
#include "content_client_qt.h"
#include "download_manager_delegate_qt.h"
#include "permission_manager_qt.h"
+#include "type_conversion.h"
#include "web_engine_context.h"
#include "web_engine_visited_links_manager.h"
#include "url_request_context_getter_qt.h"
@@ -52,6 +53,8 @@
#include "net/proxy/proxy_service.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
#include <QCoreApplication>
#include <QDir>
#include <QString>
@@ -78,6 +81,8 @@ BrowserContextAdapter::BrowserContextAdapter(bool offTheRecord)
, m_visitedLinksPolicy(TrackVisitedLinksOnDisk)
, m_httpCacheMaxSize(0)
{
+ WebEngineContext::current(); // Ensure the WebEngineContext has been initialized
+ content::BrowserContext::Initialize(m_browserContext.data(), toFilePath(dataPath()));
}
BrowserContextAdapter::BrowserContextAdapter(const QString &storageName)
@@ -89,12 +94,15 @@ BrowserContextAdapter::BrowserContextAdapter(const QString &storageName)
, m_visitedLinksPolicy(TrackVisitedLinksOnDisk)
, m_httpCacheMaxSize(0)
{
+ WebEngineContext::current(); // Ensure the WebEngineContext has been initialized
+ content::BrowserContext::Initialize(m_browserContext.data(), toFilePath(dataPath()));
}
BrowserContextAdapter::~BrowserContextAdapter()
{
if (m_downloadManagerDelegate)
content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE, m_downloadManagerDelegate.take());
+ BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(m_browserContext.data());
}
void BrowserContextAdapter::setStorageName(const QString &storageName)
diff --git a/src/core/browser_context_adapter_client.h b/src/core/browser_context_adapter_client.h
index 2df8c21cb..faba08591 100644
--- a/src/core/browser_context_adapter_client.h
+++ b/src/core/browser_context_adapter_client.h
@@ -69,6 +69,13 @@ public:
MimeHtmlSaveFormat
};
+ enum DownloadType {
+ Attachment = 0,
+ DownloadAttribute,
+ UserRequested,
+ SavePage
+ };
+
struct DownloadItemInfo {
const quint32 id;
const QUrl url;
@@ -80,6 +87,7 @@ public:
QString path;
int savePageFormat;
bool accepted;
+ int downloadType;
};
virtual ~BrowserContextAdapterClient() { }
diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp
index 1c326fb83..5f544ab86 100644
--- a/src/core/browser_context_qt.cpp
+++ b/src/core/browser_context_qt.cpp
@@ -54,31 +54,31 @@
#include "content/public/browser/storage_partition.h"
#include "net/proxy/proxy_config_service.h"
-#if defined(ENABLE_SPELLCHECK)
#include "base/base_paths.h"
-#include "base/prefs/pref_member.h"
-#include "base/prefs/pref_service.h"
-#include "base/prefs/testing_pref_store.h"
-#include "base/prefs/pref_service.h"
-#include "base/prefs/pref_service_factory.h"
-#include "base/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_member.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_store.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/pref_service_factory.h"
+#include "components/prefs/pref_registry_simple.h"
#include "components/user_prefs/user_prefs.h"
+#if defined(ENABLE_SPELLCHECK)
#include "chrome/common/pref_names.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#endif
namespace QtWebEngineCore {
-#if defined(ENABLE_SPELLCHECK)
BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter)
: m_adapter(adapter),
m_prefStore(new TestingPrefStore())
{
m_prefStore->SetInitializationCompleted();
- base::PrefServiceFactory factory;
+ PrefServiceFactory factory;
factory.set_user_prefs(m_prefStore);
scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple());
+#if defined(ENABLE_SPELLCHECK)
// Initial spellcheck settings
registry->RegisterListPref(prefs::kSpellCheckDictionaries, new base::ListValue());
registry->RegisterStringPref(prefs::kAcceptLanguages, std::string());
@@ -86,15 +86,10 @@ BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter)
registry->RegisterBooleanPref(prefs::kSpellCheckUseSpellingService, false);
registry->RegisterBooleanPref(prefs::kEnableContinuousSpellcheck, false);
registry->RegisterBooleanPref(prefs::kEnableAutoSpellCorrect, false);
+#endif //ENABLE_SPELLCHECK
m_prefService = factory.Create(std::move(registry.get()));
user_prefs::UserPrefs::Set(this, m_prefService.get());
}
-#else
-BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter)
- : m_adapter(adapter)
-{
-}
-#endif //ENABLE_SPELLCHECK
BrowserContextQt::~BrowserContextQt()
{
@@ -102,6 +97,16 @@ BrowserContextQt::~BrowserContextQt()
content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, resourceContext.release());
}
+PrefService* BrowserContextQt::GetPrefs()
+{
+ return m_prefService.get();
+}
+
+const PrefService* BrowserContextQt::GetPrefs() const
+{
+ return m_prefService.get();
+}
+
base::FilePath BrowserContextQt::GetPath() const
{
return toFilePath(m_adapter->dataPath());
@@ -122,24 +127,15 @@ net::URLRequestContextGetter *BrowserContextQt::GetRequestContext()
return url_request_getter_.get();
}
-net::URLRequestContextGetter *BrowserContextQt::GetRequestContextForRenderProcess(int)
-{
- return GetRequestContext();
-}
-
-net::URLRequestContextGetter *BrowserContextQt::GetMediaRequestContext()
-{
- return GetRequestContext();
-}
-
-net::URLRequestContextGetter *BrowserContextQt::GetMediaRequestContextForRenderProcess(int)
+net::URLRequestContextGetter *BrowserContextQt::CreateMediaRequestContext()
{
- return GetRequestContext();
+ return url_request_getter_.get();
}
-net::URLRequestContextGetter *BrowserContextQt::GetMediaRequestContextForStoragePartition(const base::FilePath&, bool)
+net::URLRequestContextGetter *BrowserContextQt::CreateMediaRequestContextForStoragePartition(const base::FilePath&, bool)
{
- return GetRequestContext();
+ Q_UNIMPLEMENTED();
+ return nullptr;
}
content::ResourceContext *BrowserContextQt::GetResourceContext()
@@ -177,7 +173,7 @@ content::SSLHostStateDelegate* BrowserContextQt::GetSSLHostStateDelegate()
return sslHostStateDelegate.get();
}
-scoped_ptr<content::ZoomLevelDelegate> BrowserContextQt::CreateZoomLevelDelegate(const base::FilePath&)
+std::unique_ptr<content::ZoomLevelDelegate> BrowserContextQt::CreateZoomLevelDelegate(const base::FilePath&)
{
return nullptr;
}
@@ -200,6 +196,15 @@ net::URLRequestContextGetter *BrowserContextQt::CreateRequestContext(content::Pr
return url_request_getter_.get();
}
+net::URLRequestContextGetter *BrowserContextQt::CreateRequestContextForStoragePartition(
+ const base::FilePath& partition_path, bool in_memory,
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors)
+{
+ Q_UNIMPLEMENTED();
+ return nullptr;
+}
+
#if defined(ENABLE_SPELLCHECK)
void BrowserContextQt::failedToLoadDictionary(const std::string &language)
{
diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h
index e2156f147..41a85b1b0 100644
--- a/src/core/browser_context_qt.h
+++ b/src/core/browser_context_qt.h
@@ -40,20 +40,18 @@
#ifndef BROWSER_CONTEXT_QT_H
#define BROWSER_CONTEXT_QT_H
-#include "content/public/browser/browser_context.h"
+#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
#include "net/url_request/url_request_context.h"
#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE
-#if defined(ENABLE_SPELLCHECK)
QT_BEGIN_NAMESPACE
class QStringList;
QT_END_NAMESPACE
class TestingPrefStore;
class PrefService;
-#endif
namespace QtWebEngineCore {
@@ -62,37 +60,48 @@ class PermissionManagerQt;
class SSLHostStateDelegateQt;
class URLRequestContextGetterQt;
-class BrowserContextQt : public content::BrowserContext
+class BrowserContextQt : public Profile
{
public:
explicit BrowserContextQt(BrowserContextAdapter *);
virtual ~BrowserContextQt();
+ // BrowserContext implementation:
virtual base::FilePath GetPath() const Q_DECL_OVERRIDE;
base::FilePath GetCachePath() const;
virtual bool IsOffTheRecord() const Q_DECL_OVERRIDE;
- virtual net::URLRequestContextGetter *GetRequestContext() Q_DECL_OVERRIDE;
- virtual net::URLRequestContextGetter *GetRequestContextForRenderProcess(int) Q_DECL_OVERRIDE;
- virtual net::URLRequestContextGetter *GetMediaRequestContext() Q_DECL_OVERRIDE;
- virtual net::URLRequestContextGetter *GetMediaRequestContextForRenderProcess(int) Q_DECL_OVERRIDE;
- virtual net::URLRequestContextGetter *GetMediaRequestContextForStoragePartition(const base::FilePath&, bool) Q_DECL_OVERRIDE;
+ net::URLRequestContextGetter *GetRequestContext();
+
+ virtual net::URLRequestContextGetter *CreateMediaRequestContext() Q_DECL_OVERRIDE;
+ virtual net::URLRequestContextGetter *CreateMediaRequestContextForStoragePartition(const base::FilePath& partition_path, bool in_memory) Q_DECL_OVERRIDE;
+
virtual content::ResourceContext *GetResourceContext() Q_DECL_OVERRIDE;
virtual content::DownloadManagerDelegate *GetDownloadManagerDelegate() Q_DECL_OVERRIDE;
virtual content::BrowserPluginGuestManager* GetGuestManager() Q_DECL_OVERRIDE;
virtual storage::SpecialStoragePolicy *GetSpecialStoragePolicy() Q_DECL_OVERRIDE;
virtual content::PushMessagingService* GetPushMessagingService() Q_DECL_OVERRIDE;
virtual content::SSLHostStateDelegate* GetSSLHostStateDelegate() Q_DECL_OVERRIDE;
- net::URLRequestContextGetter *CreateRequestContext(content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors);
- virtual scoped_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(const base::FilePath& partition_path) Q_DECL_OVERRIDE;
+ net::URLRequestContextGetter *CreateRequestContext(
+ content::ProtocolHandlerMap *protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors) Q_DECL_OVERRIDE;
+ net::URLRequestContextGetter* CreateRequestContextForStoragePartition(
+ const base::FilePath& partition_path, bool in_memory,
+ content::ProtocolHandlerMap* protocol_handlers,
+ content::URLRequestInterceptorScopedVector request_interceptors) Q_DECL_OVERRIDE;
+ virtual std::unique_ptr<content::ZoomLevelDelegate> CreateZoomLevelDelegate(const base::FilePath& partition_path) Q_DECL_OVERRIDE;
virtual content::PermissionManager *GetPermissionManager() Q_DECL_OVERRIDE;
virtual content::BackgroundSyncController* GetBackgroundSyncController() Q_DECL_OVERRIDE;
+ // Profile implementation:
+ PrefService* GetPrefs() override;
+ const PrefService* GetPrefs() const override;
+
BrowserContextAdapter *adapter() { return m_adapter; }
#if defined(ENABLE_SPELLCHECK)
- void failedToLoadDictionary(const std::string& language) override;
+ void failedToLoadDictionary(const std::string& language);
void setSpellCheckLanguage(const QString &language);
QString spellCheckLanguage() const;
void setSpellCheckEnabled(bool enabled);
@@ -102,15 +111,13 @@ public:
private:
friend class ContentBrowserClientQt;
friend class WebContentsAdapter;
- scoped_ptr<content::ResourceContext> resourceContext;
+ std::unique_ptr<content::ResourceContext> resourceContext;
scoped_refptr<URLRequestContextGetterQt> url_request_getter_;
- scoped_ptr<PermissionManagerQt> permissionManager;
- scoped_ptr<SSLHostStateDelegateQt> sslHostStateDelegate;
+ std::unique_ptr<PermissionManagerQt> permissionManager;
+ std::unique_ptr<SSLHostStateDelegateQt> sslHostStateDelegate;
BrowserContextAdapter *m_adapter;
-#if defined(ENABLE_SPELLCHECK)
scoped_refptr<TestingPrefStore> m_prefStore;
- scoped_ptr<PrefService> m_prefService;
-#endif
+ std::unique_ptr<PrefService> m_prefService;
friend class BrowserContextAdapter;
DISALLOW_COPY_AND_ASSIGN(BrowserContextQt);
diff --git a/src/core/certificate_error_controller.cpp b/src/core/certificate_error_controller.cpp
index 65bba733a..18835a5c7 100644
--- a/src/core/certificate_error_controller.cpp
+++ b/src/core/certificate_error_controller.cpp
@@ -66,6 +66,7 @@ ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateNonUniqueName, net::ER
ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateWeakKey, net::ERR_CERT_WEAK_KEY)
ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateNameConstraintViolation, net::ERR_CERT_NAME_CONSTRAINT_VIOLATION)
ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateValidityTooLong, net::ERR_CERT_VALIDITY_TOO_LONG)
+ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateTransparencyRequired, net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED)
ASSERT_ENUMS_MATCH(CertificateErrorController::CertificateErrorEnd, net::ERR_CERT_END)
void CertificateErrorControllerPrivate::accept(bool accepted)
@@ -174,6 +175,8 @@ QString CertificateErrorController::errorString() const
return getQStringForMessageId(IDS_CERT_ERROR_NAME_CONSTRAINT_VIOLATION_DESCRIPTION);
case CertificateValidityTooLong:
return getQStringForMessageId(IDS_CERT_ERROR_VALIDITY_TOO_LONG_DESCRIPTION);
+ case CertificateTransparencyRequired:
+ return getQStringForMessageId(IDS_CERT_ERROR_CERTIFICATE_TRANSPARENCY_REQUIRED_DESCRIPTION);
case CertificateUnableToCheckRevocation: // Deprecated in Chromium.
default:
break;
diff --git a/src/core/certificate_error_controller.h b/src/core/certificate_error_controller.h
index 27f18946f..554281644 100644
--- a/src/core/certificate_error_controller.h
+++ b/src/core/certificate_error_controller.h
@@ -71,8 +71,9 @@ public:
CertificateWeakKey = -211,
CertificateNameConstraintViolation = -212,
CertificateValidityTooLong = -213,
+ CertificateTransparencyRequired = -214,
- CertificateErrorEnd = -214 // not an error, just an enum boundary
+ CertificateErrorEnd = -215 // not an error, just an enum boundary
};
CertificateError error() const;
diff --git a/src/core/chrome_qt.gyp b/src/core/chrome_qt.gyp
index f2d7c5831..547f240ea 100644
--- a/src/core/chrome_qt.gyp
+++ b/src/core/chrome_qt.gyp
@@ -2,8 +2,6 @@
'variables': {
'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome',
'chrome_spellchecker_sources': [
- '<(DEPTH)/base/prefs/testing_pref_store.cc',
- '<(DEPTH)/base/prefs/testing_pref_store.h',
'<(DEPTH)/chrome/browser/spellchecker/feedback.cc',
'<(DEPTH)/chrome/browser/spellchecker/feedback.h',
'<(DEPTH)/chrome/browser/spellchecker/feedback_sender.cc',
@@ -63,6 +61,7 @@
'type': 'static_library',
'dependencies': [
'chrome_resources',
+ '<(chromium_src_dir)/components/components_resources.gyp:components_resources',
'<(chromium_src_dir)/components/components_strings.gyp:components_strings',
],
'include_dirs': [
@@ -70,43 +69,60 @@
'<(chromium_src_dir)',
'<(chromium_src_dir)/skia/config',
'<(chromium_src_dir)/third_party/skia/include/core',
- # Needed to include grit-generated files in localized_error.cc:
- '<(SHARED_INTERMEDIATE_DIR)/chrome',
- '<(SHARED_INTERMEDIATE_DIR)/components/strings',
],
'sources': [
'<(DEPTH)/chrome/browser/media/desktop_media_list.h',
'<(DEPTH)/chrome/browser/media/desktop_streams_registry.cc',
'<(DEPTH)/chrome/browser/media/desktop_streams_registry.h',
+ '<(DEPTH)/chrome/browser/profiles/profile.cc',
+ '<(DEPTH)/chrome/browser/profiles/profile.h',
'<(DEPTH)/chrome/common/chrome_switches.cc',
'<(DEPTH)/chrome/common/chrome_switches.h',
- '<(DEPTH)/chrome/common/localized_error.cc',
- '<(DEPTH)/chrome/common/localized_error.h',
+ '<(DEPTH)/components/prefs/testing_pref_store.cc',
+ '<(DEPTH)/components/prefs/testing_pref_store.h',
+ '<(DEPTH)/extensions/common/constants.cc',
+ '<(DEPTH)/extensions/common/constants.h',
+ '<(DEPTH)/extensions/common/url_pattern.cc',
+ '<(DEPTH)/extensions/common/url_pattern.h',
],
'conditions': [
+ ['OS == "win"', {
+ # crbug.com/167187 fix size_t to int truncations
+ 'msvs_disabled_warnings': [4267, ],
+ }],
+ ['enable_plugins==1', {
+ 'sources': [
+ '<(DEPTH)/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc',
+ '<(DEPTH)/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h',
+ '<(DEPTH)/chrome/renderer/pepper/pepper_flash_font_file_host.cc',
+ '<(DEPTH)/chrome/renderer/pepper/pepper_flash_font_file_host.h',
+ '<(DEPTH)/chrome/renderer/pepper/pepper_shared_memory_message_filter.cc',
+ '<(DEPTH)/chrome/renderer/pepper/pepper_shared_memory_message_filter.h',
+ ],
+ }],
+ ['enable_pdf==1', {
+ 'dependencies': [
+ '<(chromium_src_dir)/pdf/pdf.gyp:pdf',
+ '<(chromium_src_dir)/components/components.gyp:pdf_renderer',
+ '<(chromium_src_dir)/components/components.gyp:pdf_browser',
+ ],
+ }],
['enable_spellcheck==1', {
'sources': [ '<@(chrome_spellchecker_sources)' ],
'include_dirs': [
- '<(chromium_src_dir)/third_party/WebKit',
+ '<(chromium_src_dir)/third_party/WebKit',
],
'dependencies': [
- '<(chromium_src_dir)/components/components.gyp:keyed_service_content',
- '<(chromium_src_dir)/components/components.gyp:keyed_service_core',
- '<(chromium_src_dir)/components/components.gyp:pref_registry',
- '<(chromium_src_dir)/components/components.gyp:user_prefs',
- '<(chromium_src_dir)/third_party/hunspell/hunspell.gyp:hunspell',
- '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n',
- '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
+ '<(chromium_src_dir)/chrome/tools/convert_dict/convert_dict.gyp:convert_dict_lib',
+ '<(chromium_src_dir)/third_party/hunspell/hunspell.gyp:hunspell',
+ '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n',
+ '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc',
],
'defines': [
'__STDC_CONSTANT_MACROS',
'__STDC_FORMAT_MACROS',
],
'conditions': [
- ['OS == "win"', {
- # crbug.com/167187 fix size_t to int truncations
- 'msvs_disabled_warnings': [4267, ],
- }],
[ 'OS != "mac"', {
'sources/': [
['exclude', '_mac\\.(cc|cpp|mm?)$'],
@@ -134,7 +150,7 @@
'<(DEPTH)/chrome/browser/printing/printer_query.h',
],
'dependencies': [
- '<(chromium_src_dir)/third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '<(chromium_src_dir)/mojo/mojo_public.gyp:mojo_cpp_bindings',
],
'include_dirs': [
'<(chromium_src_dir)/extensions',
diff --git a/src/core/chromium_gpu_helper.cpp b/src/core/chromium_gpu_helper.cpp
index 349506dbd..d1133f5c2 100644
--- a/src/core/chromium_gpu_helper.cpp
+++ b/src/core/chromium_gpu_helper.cpp
@@ -50,13 +50,14 @@
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_manager.h"
-#include "content/common/gpu/gpu_channel_manager.h"
#include "content/gpu/gpu_child_thread.h"
+#include "gpu/ipc/service/gpu_channel_manager.h"
#ifdef Q_OS_QNX
#include "content/common/gpu/stream_texture_qnx.h"
#endif
+// FIXME: Try using content::GpuChildThread::current()
base::MessageLoop *gpu_message_loop()
{
return content::GpuChildThread::instance()->message_loop();
@@ -64,13 +65,13 @@ base::MessageLoop *gpu_message_loop()
gpu::SyncPointManager *sync_point_manager()
{
- content::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager();
+ gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager();
return gpuChannelManager->sync_point_manager();
}
gpu::gles2::MailboxManager *mailbox_manager()
{
- content::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager();
+ gpu::GpuChannelManager *gpuChannelManager = content::GpuChildThread::instance()->ChannelManager();
return gpuChannelManager->mailbox_manager();
}
diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp
index 18596c337..882f5b1dd 100644
--- a/src/core/chromium_overrides.cpp
+++ b/src/core/chromium_overrides.cpp
@@ -119,9 +119,9 @@ void RenderWidgetHostViewBase::GetDefaultScreenInfo(blink::WebScreenInfo* result
namespace content {
// content/common/font_list.h
-scoped_ptr<base::ListValue> GetFontList_SlowBlocking()
+std::unique_ptr<base::ListValue> GetFontList_SlowBlocking()
{
- scoped_ptr<base::ListValue> font_list(new base::ListValue);
+ std::unique_ptr<base::ListValue> font_list(new base::ListValue);
QFontDatabase database;
for (auto family : database.families()){
@@ -166,9 +166,9 @@ namespace net {
class SSLPrivateKey { };
class X509Certificate;
-scoped_ptr<SSLPrivateKey> FetchClientCertPrivateKey(X509Certificate* certificate)
+std::unique_ptr<SSLPrivateKey> FetchClientCertPrivateKey(X509Certificate* certificate)
{
- return scoped_ptr<SSLPrivateKey>();
+ return std::unique_ptr<SSLPrivateKey>();
}
} // namespace net
diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h
index b8991a2b3..2c971aab2 100644
--- a/src/core/common/qt_messages.h
+++ b/src/core/common/qt_messages.h
@@ -16,6 +16,9 @@ IPC_STRUCT_TRAITS_BEGIN(UserScriptData)
IPC_STRUCT_TRAITS_MEMBER(injectForSubframes)
IPC_STRUCT_TRAITS_MEMBER(worldId)
IPC_STRUCT_TRAITS_MEMBER(scriptId)
+ IPC_STRUCT_TRAITS_MEMBER(globs)
+ IPC_STRUCT_TRAITS_MEMBER(excludeGlobs)
+ IPC_STRUCT_TRAITS_MEMBER(urlPatterns)
IPC_STRUCT_TRAITS_END()
diff --git a/src/core/common/user_script_data.h b/src/core/common/user_script_data.h
index 943d61798..8d98890e3 100644
--- a/src/core/common/user_script_data.h
+++ b/src/core/common/user_script_data.h
@@ -60,6 +60,9 @@ struct UserScriptData {
bool injectForSubframes;
uint worldId;
uint64_t scriptId;
+ std::vector<std::string> globs;
+ std::vector<std::string> excludeGlobs;
+ std::vector<std::string> urlPatterns;
};
QT_BEGIN_NAMESPACE
diff --git a/src/core/config/common.pri b/src/core/config/common.pri
index 5822bc589..01c942976 100644
--- a/src/core/config/common.pri
+++ b/src/core/config/common.pri
@@ -2,10 +2,10 @@
# Trigger Qt-specific build conditions.
GYP_CONFIG += use_qt=1
+# Enable printing. We enable preview because we use preview logic even if we don't support preview.
+GYP_CONFIG += enable_basic_printing=1 enable_print_preview=1
# We do not want to ship more external binary blobs, so let v8 embed its startup data.
GYP_CONFIG += v8_use_external_startup_data=0
-# Disable printing since we don't support it yet
-GYP_CONFIG += enable_basic_printing=1 enable_print_preview=0
# WebSpeech requires Google API keys and adds dependencies on speex and flac.
GYP_CONFIG += enable_web_speech=0
# We do not use or even include the extensions
diff --git a/src/core/config/desktop_linux.pri b/src/core/config/desktop_linux.pri
index de0fbbc6b..46d500207 100644
--- a/src/core/config/desktop_linux.pri
+++ b/src/core/config/desktop_linux.pri
@@ -4,7 +4,8 @@ include(linux.pri)
GYP_CONFIG += \
desktop_linux=1 \
- enable_widevine=1
+ enable_widevine=1 \
+ enable_pdf=1
clang {
GYP_CONFIG += clang=1 host_clang=1 clang_use_chrome_plugins=0 make_clang_dir=/usr
diff --git a/src/core/config/embedded_linux.pri b/src/core/config/embedded_linux.pri
index 4cb7d89fb..844877e03 100644
--- a/src/core/config/embedded_linux.pri
+++ b/src/core/config/embedded_linux.pri
@@ -15,9 +15,10 @@ GYP_CONFIG += \
enable_google_now=0 \
enable_language_detection=0 \
enable_managed_users=0 \
+ enable_pdf=0 \
enable_plugin_installation=0 \
enable_plugins=0 \
- enable_printing=0 \
+ enable_print_preview=0 \
enable_session_service=0 \
enable_task_manager=0 \
enable_themes=0 \
diff --git a/src/core/config/embedded_qnx.pri b/src/core/config/embedded_qnx.pri
index c05e8bb59..3effdb816 100644
--- a/src/core/config/embedded_qnx.pri
+++ b/src/core/config/embedded_qnx.pri
@@ -5,6 +5,7 @@ include(common.pri)
GYP_CONFIG += \
disable_nacl=1 \
enable_basic_printing=0 \
+ enable_pdf=0 \
enable_plugins=0 \
enable_webrtc=0 \
use_ash=0 \
diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri
index a318e170c..fc2b124fb 100644
--- a/src/core/config/linux.pri
+++ b/src/core/config/linux.pri
@@ -1,4 +1,5 @@
include(common.pri)
+QT_FOR_CONFIG += gui-private
# linux_use_bundled_gold currently relies on a hardcoded relative path from chromium/src/out/(Release|Debug)
# Disable it along with the -Wl,--threads flag just in case gold isn't installed on the system.
@@ -22,19 +23,24 @@ GYP_CONFIG += \
use_openssl=1
use?(nss) {
- GYP_CONFIG += use_nss_certs=1 \
+ GYP_CONFIG += \
+ use_nss_certs=1 \
+ use_nss_verifier=1 \
use_openssl_certs=0
} else {
- GYP_CONFIG += use_nss_certs=0 \
+ GYP_CONFIG += \
+ use_nss_certs=0 \
+ use_nss_verifier=0 \
use_openssl_certs=1
}
gcc:!clang: greaterThan(QT_GCC_MAJOR_VERSION, 5): GYP_CONFIG += no_delete_null_pointer_checks=1
-contains(QT_CONFIG, system-zlib): use?(system_minizip): GYP_CONFIG += use_system_zlib=1
-contains(QT_CONFIG, system-png): GYP_CONFIG += use_system_libpng=1
-contains(QT_CONFIG, system-jpeg): GYP_CONFIG += use_system_libjpeg=1
-contains(QT_CONFIG, system-harfbuzz): GYP_CONFIG += use_system_harfbuzz=1
+qtConfig(system-zlib): use?(system_minizip): GYP_CONFIG += use_system_zlib=1
+qtConfig(system-png): GYP_CONFIG += use_system_libpng=1
+qtConfig(system-jpeg): GYP_CONFIG += use_system_libjpeg=1
+qtConfig(system-harfbuzz): GYP_CONFIG += use_system_harfbuzz=1
+!qtConfig(glib): GYP_CONFIG += use_glib=0
contains(QT_CONFIG, pulseaudio) {
GYP_CONFIG += use_pulseaudio=1
} else {
@@ -45,7 +51,6 @@ contains(QT_CONFIG, alsa) {
} else {
GYP_CONFIG += use_alsa=0
}
-!contains(QT_CONFIG, glib): GYP_CONFIG += use_glib=0
use?(system_libevent): GYP_CONFIG += use_system_libevent=1
use?(system_libwebp): GYP_CONFIG += use_system_libwebp=1
use?(system_libsrtp): GYP_CONFIG += use_system_libsrtp=1
diff --git a/src/core/config/mac_osx.pri b/src/core/config/mac_osx.pri
index c447add4a..55601ded9 100644
--- a/src/core/config/mac_osx.pri
+++ b/src/core/config/mac_osx.pri
@@ -25,7 +25,8 @@ GYP_CONFIG += \
mac_deployment_target=\"$${QMAKE_MACOSX_DEPLOYMENT_TARGET}\" \
make_clang_dir=\"$${QMAKE_CLANG_DIR}\" \
clang_use_chrome_plugins=0 \
- enable_widevine=1
+ enable_widevine=1 \
+ enable_pdf=1
# Force touch API is used in 49-based Chromium, which is included starting with 10.10.3 SDK, so we
# disable the API usage if the SDK version is lower.
diff --git a/src/core/config/windows.pri b/src/core/config/windows.pri
index a99bc5303..5b9551b5a 100644
--- a/src/core/config/windows.pri
+++ b/src/core/config/windows.pri
@@ -6,7 +6,8 @@ GYP_CONFIG += \
disable_nacl=1 \
remoting=0 \
use_ash=0 \
- enable_widevine=1
+ enable_widevine=1 \
+ enable_pdf=1
# Libvpx build needs additional search path on Windows.
GYP_ARGS += "-D qtwe_chromium_obj_dir=\"$$OUT_PWD/$$getConfigDir()/obj/$${getChromiumSrcDir()}\""
@@ -17,7 +18,7 @@ GYP_ARGS += "-D perl_exe=\"perl.exe\" -D bison_exe=\"bison.exe\" -D gperf_exe=\"
# Gyp's parallel processing is broken on Windows
GYP_ARGS += "--no-parallel"
-contains(QT_CONFIG, angle) {
+qtConfig(angle) {
CONFIG(release, debug|release) {
GYP_ARGS += "-D qt_egl_library=\"libEGL.lib\" -D qt_glesv2_library=\"libGLESv2.lib\""
} else {
@@ -56,9 +57,7 @@ msvc:contains(QT_ARCH, "i386"):!usingMSVC32BitCrossCompiler() {
}
msvc {
- equals(MSVC_VER, 12.0) {
- MSVS_VERSION = 2013
- } else:equals(MSVC_VER, 14.0) {
+ equals(MSVC_VER, 14.0) {
MSVS_VERSION = 2015
} else {
fatal("Visual Studio compiler version \"$$MSVC_VER\" is not supported by Qt WebEngine")
@@ -66,7 +65,7 @@ msvc {
GYP_ARGS += "-G msvs_version=$$MSVS_VERSION"
- isBuildingOnWin32(): GYP_ARGS += "-D windows_sdk_path=\"C:/Program Files/Windows Kits/8.1\""
+ isBuildingOnWin32(): GYP_ARGS += "-D windows_sdk_path=\"C:/Program Files/Windows Kits/10\""
} else {
fatal("Qt WebEngine for Windows can only be built with the Microsoft Visual Studio C++ compiler")
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index f5f490ccf..5131d8229 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -39,6 +39,7 @@
#include "content_browser_client_qt.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_restrictions.h"
#if defined(ENABLE_SPELLCHECK)
@@ -47,6 +48,7 @@
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/public/browser/browser_main_parts.h"
#include "content/public/browser/child_process_security_policy.h"
+#include "content/public/browser/geolocation_delegate.h"
#include "content/public/browser/media_observer.h"
#include "content/public/browser/quota_permission_context.h"
#include "content/public/browser/render_frame_host.h"
@@ -58,7 +60,7 @@
#include "content/public/common/main_function_params.h"
#include "content/public/common/url_constants.h"
#include "ui/base/ui_base_switches.h"
-#include "ui/gfx/screen.h"
+#include "ui/display/screen.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_share_group.h"
@@ -85,6 +87,11 @@
#include "web_engine_context.h"
#include "web_engine_library_info.h"
+#if defined(Q_OS_LINUX)
+#include "global_descriptors_qt.h"
+#include "ui/base/resource/resource_bundle.h"
+#endif
+
#if defined(ENABLE_PLUGINS)
#include "content/public/browser/browser_ppapi_host.h"
#include "ppapi/host/ppapi_host.h"
@@ -211,9 +218,9 @@ private:
base::TimeTicks m_timerScheduledTime;
};
-scoped_ptr<base::MessagePump> messagePumpFactory()
+std::unique_ptr<base::MessagePump> messagePumpFactory()
{
- return scoped_ptr<base::MessagePump>(new MessagePumpForUIQt);
+ return base::WrapUnique(new MessagePumpForUIQt);
}
} // namespace
@@ -244,8 +251,9 @@ public:
int PreCreateThreads() Q_DECL_OVERRIDE
{
base::ThreadRestrictions::SetIOAllowed(true);
- // Like ChromeBrowserMainExtraPartsAura::PreCreateThreads does.
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, new DesktopScreenQt);
+ // Like ChromeBrowserMainExtraPartsViews::PreCreateThreads does.
+ display::Screen::SetScreenInstance(new DesktopScreenQt);
+
return 0;
}
@@ -253,16 +261,16 @@ private:
DISALLOW_COPY_AND_ASSIGN(BrowserMainPartsQt);
};
-class QtShareGLContext : public gfx::GLContext {
+class QtShareGLContext : public gl::GLContext {
public:
QtShareGLContext(QOpenGLContext *qtContext)
- : gfx::GLContext(0)
+ : gl::GLContext(0)
, m_handle(0)
{
QString platform = qApp->platformName().toLower();
QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface();
if (platform == QLatin1String("xcb")) {
- if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
+ if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2)
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext);
else
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("glxcontext"), qtContext);
@@ -273,7 +281,7 @@ public:
else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland"))
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext);
else if (platform == QLatin1String("windows")) {
- if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
+ if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2)
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglContext"), qtContext);
else
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("renderingcontext"), qtContext);
@@ -289,12 +297,12 @@ public:
virtual bool WasAllocatedUsingRobustnessExtension() { return false; }
// We don't care about the rest, this context shouldn't be used except for its handle.
- virtual bool Initialize(gfx::GLSurface *, gfx::GpuPreference) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; }
- virtual bool MakeCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; }
- virtual void ReleaseCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); }
- virtual bool IsCurrent(gfx::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; }
+ virtual bool Initialize(gl::GLSurface *, gl::GpuPreference) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; }
+ virtual bool MakeCurrent(gl::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; }
+ virtual void ReleaseCurrent(gl::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); }
+ virtual bool IsCurrent(gl::GLSurface *) Q_DECL_OVERRIDE { Q_UNREACHABLE(); return false; }
virtual void OnSetSwapInterval(int) Q_DECL_OVERRIDE { Q_UNREACHABLE(); }
- virtual scoped_refptr<gfx::GPUTimingClient> CreateGPUTimingClient() Q_DECL_OVERRIDE
+ virtual scoped_refptr<gl::GPUTimingClient> CreateGPUTimingClient() Q_DECL_OVERRIDE
{
return nullptr;
}
@@ -303,9 +311,9 @@ private:
void *m_handle;
};
-class ShareGroupQtQuick : public gfx::GLShareGroup {
+class ShareGroupQtQuick : public gl::GLShareGroup {
public:
- virtual gfx::GLContext* GetContext() Q_DECL_OVERRIDE { return m_shareContextQtQuick.get(); }
+ virtual gl::GLContext* GetContext() Q_DECL_OVERRIDE { return m_shareContextQtQuick.get(); }
virtual void AboutToAddFirstContext() Q_DECL_OVERRIDE;
private:
@@ -351,7 +359,7 @@ ContentBrowserClientQt *ContentBrowserClientQt::Get()
content::BrowserMainParts *ContentBrowserClientQt::CreateBrowserMainParts(const content::MainFunctionParams&)
{
- m_browserMainParts = new BrowserMainPartsQt;
+ m_browserMainParts = new BrowserMainPartsQt();
return m_browserMainParts;
}
@@ -378,7 +386,7 @@ void ContentBrowserClientQt::ResourceDispatcherHostCreated()
content::ResourceDispatcherHost::Get()->SetDelegate(m_resourceDispatcherHostDelegate.get());
}
-gfx::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup()
+gl::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup()
{
if (!m_shareGroupQtQuick.get())
m_shareGroupQtQuick = new ShareGroupQtQuick;
@@ -396,14 +404,41 @@ void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, c
static_cast<WebContentsDelegateQt*>(webContents->GetDelegate())->overrideWebPreferences(webContents, web_prefs);
}
-content::AccessTokenStore *ContentBrowserClientQt::CreateAccessTokenStore()
-{
- return new AccessTokenStoreQt;
-}
+namespace {
+
+// A provider of services needed by Geolocation.
+class GeolocationDelegateQt : public content::GeolocationDelegate {
+public:
+ GeolocationDelegateQt() {}
+ content::AccessTokenStore* CreateAccessTokenStore() final
+ {
+ return new AccessTokenStoreQt;
+ }
-net::URLRequestContextGetter* ContentBrowserClientQt::CreateRequestContext(content::BrowserContext* browser_context, content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors)
+ content::LocationProvider* OverrideSystemLocationProvider() final
+ {
+#ifdef QT_USE_POSITIONING
+ if (!m_location_provider)
+ m_location_provider = base::WrapUnique(new LocationProviderQt);
+ return m_location_provider.get();
+#else
+ return nullptr;
+#endif
+ }
+
+private:
+#ifdef QT_USE_POSITIONING
+ std::unique_ptr<LocationProviderQt> m_location_provider;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(GeolocationDelegateQt);
+};
+
+} // anonymous namespace
+
+content::GeolocationDelegate *ContentBrowserClientQt::CreateGeolocationDelegate()
{
- return static_cast<BrowserContextQt*>(browser_context)->CreateRequestContext(protocol_handlers, std::move(request_interceptors));
+ return new GeolocationDelegateQt;
}
content::QuotaPermissionContext *ContentBrowserClientQt::CreateQuotaPermissionContext()
@@ -433,15 +468,6 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont
*result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
}
-content::LocationProvider *ContentBrowserClientQt::OverrideSystemLocationProvider()
-{
-#ifdef QT_USE_POSITIONING
- return new LocationProviderQt;
-#else
- return 0; // Leave it up to Chromium to figure something out.
-#endif
-}
-
std::string ContentBrowserClientQt::GetApplicationLocale()
{
return WebEngineLibraryInfo::getApplicationLocale();
@@ -461,11 +487,28 @@ void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* c
command_line->AppendSwitchASCII(switches::kLang, GetApplicationLocale());
}
+#if defined(Q_OS_LINUX)
+void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::FileDescriptorInfo* mappings)
+{
+ const std::string &locale = GetApplicationLocale();
+ const base::FilePath &locale_file_path = ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(locale, true);
+ if (locale_file_path.empty())
+ return;
+
+ // Open pak file of the current locale in the Browser process and pass its file descriptor to the sandboxed
+ // Renderer Process. FileDescriptorInfo is responsible for closing the file descriptor.
+ int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
+ base::File locale_file = base::File(locale_file_path, flags);
+ mappings->Transfer(kWebEngineLocale, base::ScopedFD(locale_file.TakePlatformFile()));
+}
+#endif
+
#if defined(ENABLE_PLUGINS)
- void ContentBrowserClientQt::DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) {
- browser_host->GetPpapiHost()->AddHostFactoryFilter(
- scoped_ptr<ppapi::host::HostFactory>(new QtWebEngineCore::PepperHostFactoryQt(browser_host)));
- }
+void ContentBrowserClientQt::DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host)
+{
+ browser_host->GetPpapiHost()->AddHostFactoryFilter(
+ base::WrapUnique(new QtWebEngineCore::PepperHostFactoryQt(browser_host)));
+}
#endif
content::DevToolsManagerDelegate* ContentBrowserClientQt::GetDevToolsManagerDelegate()
diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h
index 1878e3d27..acbf1a059 100644
--- a/src/core/content_browser_client_qt.h
+++ b/src/core/content_browser_client_qt.h
@@ -41,9 +41,7 @@
#define CONTENT_BROWSER_CLIENT_QT_H
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/public/browser/content_browser_client.h"
-#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h"
#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE
@@ -68,7 +66,7 @@ class WebContents;
struct MainFunctionParams;
}
-namespace gfx {
+namespace gl {
class GLShareGroup;
}
@@ -87,9 +85,9 @@ public:
virtual content::BrowserMainParts* CreateBrowserMainParts(const content::MainFunctionParams&) Q_DECL_OVERRIDE;
virtual void RenderProcessWillLaunch(content::RenderProcessHost* host) Q_DECL_OVERRIDE;
virtual void ResourceDispatcherHostCreated() Q_DECL_OVERRIDE;
- virtual gfx::GLShareGroup* GetInProcessGpuShareGroup() Q_DECL_OVERRIDE;
+ virtual gl::GLShareGroup* GetInProcessGpuShareGroup() Q_DECL_OVERRIDE;
virtual content::MediaObserver* GetMediaObserver() Q_DECL_OVERRIDE;
- virtual content::AccessTokenStore* CreateAccessTokenStore() Q_DECL_OVERRIDE;
+ virtual content::GeolocationDelegate* CreateGeolocationDelegate() Q_DECL_OVERRIDE;
virtual content::QuotaPermissionContext *CreateQuotaPermissionContext() Q_DECL_OVERRIDE;
virtual void OverrideWebkitPrefs(content::RenderViewHost *, content::WebPreferences *) Q_DECL_OVERRIDE;
virtual void AllowCertificateError(content::WebContents* web_contents,
@@ -102,21 +100,23 @@ public:
bool expired_previous_decision,
const base::Callback<void(bool)>& callback,
content::CertificateRequestResultType* result) Q_DECL_OVERRIDE;
- content::LocationProvider* OverrideSystemLocationProvider() Q_DECL_OVERRIDE;
content::DevToolsManagerDelegate *GetDevToolsManagerDelegate() Q_DECL_OVERRIDE;
- virtual net::URLRequestContextGetter *CreateRequestContext(content::BrowserContext *browser_context, content::ProtocolHandlerMap *protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptorss) Q_DECL_OVERRIDE;
virtual std::string GetApplicationLocale() Q_DECL_OVERRIDE;
std::string GetAcceptLangs(content::BrowserContext* context) Q_DECL_OVERRIDE;
virtual void AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) Q_DECL_OVERRIDE;
+#if defined(Q_OS_LINUX)
+ virtual void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::FileDescriptorInfo* mappings) Q_DECL_OVERRIDE;
+#endif
+
#if defined(ENABLE_PLUGINS)
virtual void DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) Q_DECL_OVERRIDE;
#endif
private:
BrowserMainPartsQt* m_browserMainParts;
- scoped_ptr<ResourceDispatcherHostDelegateQt> m_resourceDispatcherHostDelegate;
+ std::unique_ptr<ResourceDispatcherHostDelegateQt> m_resourceDispatcherHostDelegate;
scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick;
};
diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp
index 0418873be..2725ab9e4 100644
--- a/src/core/content_client_qt.cpp
+++ b/src/core/content_client_qt.cpp
@@ -92,8 +92,6 @@ const char kPpapiFlashVersion[] = "ppapi-flash-version";
const char kPpapiWidevinePath[] = "ppapi-widevine-path";
}
-static const base::FilePath::CharType kWidevineCdmBaseDirectory[] = FILE_PATH_LITERAL("WidevineCDM");
-
static const char kWidevineCdmPluginExtension[] = "";
static const int32_t kWidevineCdmPluginPermissions = ppapi::PERMISSION_DEV
@@ -247,11 +245,9 @@ void AddPepperWidevine(std::vector<content::PepperPluginInfo>* plugins)
// Add the supported codecs as if they came from the component manifest.
std::vector<std::string> codecs;
- codecs.push_back(kCdmSupportedCodecVorbis);
codecs.push_back(kCdmSupportedCodecVp8);
codecs.push_back(kCdmSupportedCodecVp9);
#if defined(USE_PROPRIETARY_CODECS)
- codecs.push_back(kCdmSupportedCodecAac);
codecs.push_back(kCdmSupportedCodecAvc1);
#endif // defined(USE_PROPRIETARY_CODECS)
std::string codec_string =
diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp
index 8bd07ef75..095e54caa 100644
--- a/src/core/content_main_delegate_qt.cpp
+++ b/src/core/content_main_delegate_qt.cpp
@@ -59,7 +59,9 @@
#include "base/cpu.h"
#endif
-#include <QLocale>
+#if defined(OS_LINUX)
+#include "ui/base/ui_base_switches.h"
+#endif
namespace QtWebEngineCore {
@@ -110,6 +112,12 @@ void ContentMainDelegateQt::PreSandboxStartup()
logging::LoggingSettings settings;
settings.logging_dest = DetermineLogMode(*parsedCommandLine);
logging::InitLogging(settings);
+ // view the logs with process/thread IDs and timestamps
+ logging::SetLogItems(true, //enable_process_id
+ true, //enable_thread_id
+ true, //enable_timestamp
+ false //enable_tickcount
+ );
if (logging::GetMinLogLevel() >= logging::LOG_INFO) {
if (parsedCommandLine->HasSwitch(switches::kLoggingLevel)) {
@@ -129,6 +137,15 @@ content::ContentBrowserClient *ContentMainDelegateQt::CreateContentBrowserClient
content::ContentRendererClient *ContentMainDelegateQt::CreateContentRendererClient()
{
+#if defined(OS_LINUX)
+ base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
+
+ if (parsedCommandLine->HasSwitch(switches::kLang)) {
+ const std::string &locale = parsedCommandLine->GetSwitchValueASCII(switches::kLang);
+ ui::ResourceBundle::GetSharedInstance().ReloadLocaleResources(locale);
+ }
+#endif
+
return new ContentRendererClientQt;
}
diff --git a/src/core/content_main_delegate_qt.h b/src/core/content_main_delegate_qt.h
index dd7f38f69..3cb3b3bb3 100644
--- a/src/core/content_main_delegate_qt.h
+++ b/src/core/content_main_delegate_qt.h
@@ -42,7 +42,6 @@
#include "content/public/app/content_main_delegate.h"
-#include "base/memory/scoped_ptr.h"
#include <QtCore/qcompilerdetection.h>
#include "content_browser_client_qt.h"
@@ -63,7 +62,7 @@ public:
bool BasicStartupComplete(int* /*exit_code*/) Q_DECL_OVERRIDE;
private:
- scoped_ptr<ContentBrowserClientQt> m_browserClient;
+ std::unique_ptr<ContentBrowserClientQt> m_browserClient;
};
} // namespace QtWebEngineCore
diff --git a/src/core/cookie_monster_delegate_qt.cpp b/src/core/cookie_monster_delegate_qt.cpp
index 5a4c8e707..4e52f562a 100644
--- a/src/core/cookie_monster_delegate_qt.cpp
+++ b/src/core/cookie_monster_delegate_qt.cpp
@@ -40,6 +40,7 @@
#include "cookie_monster_delegate_qt.h"
#include "base/bind.h"
+#include "base/memory/ptr_util.h"
#include "content/public/browser/browser_thread.h"
#include "net/cookies/cookie_util.h"
@@ -55,11 +56,14 @@ static GURL sourceUrlForCookie(const QNetworkCookie &cookie) {
}
static void onSetCookieCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, bool success) {
- client->onSetCallbackResult(callbackId, success);
+
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&QWebEngineCookieStorePrivate::onSetCallbackResult, base::Unretained(client), callbackId, success));
}
static void onDeleteCookiesCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, int numCookies) {
- client->onDeleteCallbackResult(callbackId, numCookies);
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&QWebEngineCookieStorePrivate::onDeleteCallbackResult, base::Unretained(client), callbackId, numCookies));
}
static void onGetAllCookiesCallback(QWebEngineCookieStorePrivate *client, qint64 callbackId, const net::CookieList& cookies) {
@@ -67,14 +71,14 @@ static void onGetAllCookiesCallback(QWebEngineCookieStorePrivate *client, qint64
for (auto&& cookie: cookies)
rawCookies += toQt(cookie).toRawForm() % QByteArrayLiteral("\n");
- client->onGetAllCallbackResult(callbackId, rawCookies);
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&QWebEngineCookieStorePrivate::onGetAllCallbackResult, base::Unretained(client), callbackId, rawCookies));
}
CookieMonsterDelegateQt::CookieMonsterDelegateQt()
: m_client(0)
- , m_cookieMonster(0)
+ , m_cookieMonster(nullptr)
{
-
}
CookieMonsterDelegateQt::~CookieMonsterDelegateQt()
@@ -84,13 +88,21 @@ CookieMonsterDelegateQt::~CookieMonsterDelegateQt()
bool CookieMonsterDelegateQt::hasCookieMonster()
{
- return m_cookieMonster.get();
+ return m_cookieMonster;
}
void CookieMonsterDelegateQt::getAllCookies(quint64 callbackId)
{
net::CookieMonster::GetCookieListCallback callback = base::Bind(&onGetAllCookiesCallback, m_client->d_func(), callbackId);
- m_cookieMonster->GetAllCookiesAsync(callback);
+
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&CookieMonsterDelegateQt::GetAllCookiesOnIOThread, this, callback));
+}
+
+void CookieMonsterDelegateQt::GetAllCookiesOnIOThread(const net::CookieMonster::GetCookieListCallback& callback)
+{
+ if (m_cookieMonster)
+ m_cookieMonster->GetAllCookiesAsync(callback);
}
void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie &cookie, const QUrl &origin)
@@ -102,12 +114,22 @@ void CookieMonsterDelegateQt::setCookie(quint64 callbackId, const QNetworkCookie
if (callbackId != CallbackDirectory::NoCallbackId)
callback = base::Bind(&onSetCookieCallback, m_client->d_func(), callbackId);
+ GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin);
+
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&CookieMonsterDelegateQt::SetCookieOnIOThread, this,
+ gurl, cookie.toRawForm().toStdString(), callback));
+}
+
+void CookieMonsterDelegateQt::SetCookieOnIOThread(
+ const GURL& url, const std::string& cookie_line,
+ const net::CookieMonster::SetCookiesCallback& callback)
+{
net::CookieOptions options;
options.set_include_httponly();
- GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin);
-
- m_cookieMonster->SetCookieWithOptionsAsync(gurl, cookie.toRawForm().toStdString(), options, callback);
+ if (m_cookieMonster)
+ m_cookieMonster->SetCookieWithOptionsAsync(url, cookie_line, options, callback);
}
void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const QUrl &origin)
@@ -117,7 +139,15 @@ void CookieMonsterDelegateQt::deleteCookie(const QNetworkCookie &cookie, const Q
GURL gurl = origin.isEmpty() ? sourceUrlForCookie(cookie) : toGurl(origin);
- m_cookieMonster->DeleteCookieAsync(gurl, cookie.name().toStdString(), base::Closure());
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&CookieMonsterDelegateQt::DeleteCookieOnIOThread, this,
+ gurl, cookie.name().toStdString()));
+}
+
+void CookieMonsterDelegateQt::DeleteCookieOnIOThread(const GURL& url, const std::string& cookie_name)
+{
+ if (m_cookieMonster)
+ m_cookieMonster->DeleteCookieAsync(url, cookie_name, base::Closure());
}
void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId)
@@ -126,7 +156,14 @@ void CookieMonsterDelegateQt::deleteSessionCookies(quint64 callbackId)
Q_ASSERT(m_client);
net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId);
- m_cookieMonster->DeleteSessionCookiesAsync(callback);
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread, this, callback));
+}
+
+void CookieMonsterDelegateQt::DeleteSessionCookiesOnIOThread(const net::CookieMonster::DeleteCallback& callback)
+{
+ if (m_cookieMonster)
+ m_cookieMonster->DeleteSessionCookiesAsync(callback);
}
void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId)
@@ -135,7 +172,14 @@ void CookieMonsterDelegateQt::deleteAllCookies(quint64 callbackId)
Q_ASSERT(m_client);
net::CookieMonster::DeleteCallback callback = base::Bind(&onDeleteCookiesCallback, m_client->d_func(), callbackId);
- m_cookieMonster->DeleteAllAsync(callback);
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&CookieMonsterDelegateQt::DeleteAllOnIOThread, this, callback));
+}
+
+void CookieMonsterDelegateQt::DeleteAllOnIOThread(const net::CookieMonster::DeleteCallback& callback)
+{
+ if (m_cookieMonster)
+ m_cookieMonster->DeleteAllAsync(callback);
}
void CookieMonsterDelegateQt::setCookieMonster(net::CookieMonster* monster)
diff --git a/src/core/cookie_monster_delegate_qt.h b/src/core/cookie_monster_delegate_qt.h
index 2ff5eeaa6..f47dc86df 100644
--- a/src/core/cookie_monster_delegate_qt.h
+++ b/src/core/cookie_monster_delegate_qt.h
@@ -66,7 +66,7 @@ static const char* const kCookieableSchemes[] =
class QWEBENGINE_EXPORT CookieMonsterDelegateQt: public net::CookieMonsterDelegate {
QPointer<QWebEngineCookieStore> m_client;
- scoped_refptr<net::CookieMonster> m_cookieMonster;
+ net::CookieMonster *m_cookieMonster;
public:
CookieMonsterDelegateQt();
~CookieMonsterDelegateQt();
@@ -84,6 +84,13 @@ public:
bool canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url);
void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed, ChangeCause cause) override;
+
+private:
+ void GetAllCookiesOnIOThread(const net::CookieMonster::GetCookieListCallback& callback);
+ void SetCookieOnIOThread(const GURL& url, const std::string& cookie_line, const net::CookieMonster::SetCookiesCallback& callback);
+ void DeleteCookieOnIOThread(const GURL& url, const std::string& cookie_name);
+ void DeleteSessionCookiesOnIOThread(const net::CookieMonster::DeleteCallback& callback);
+ void DeleteAllOnIOThread(const net::CookieMonster::DeleteCallback& callback);
};
}
diff --git a/src/core/core_common.pri b/src/core/core_common.pri
index 9c29aea71..721e8c71a 100644
--- a/src/core/core_common.pri
+++ b/src/core/core_common.pri
@@ -10,3 +10,4 @@ CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir()
INCLUDEPATH += $$CHROMIUM_SRC_DIR
qtHaveModule(positioning):QT += positioning
+qtHaveModule(printsupport):QT += printsupport
diff --git a/src/core/core_gyp_generator.pro b/src/core/core_gyp_generator.pro
index 7351b108c..5196d6438 100644
--- a/src/core/core_gyp_generator.pro
+++ b/src/core/core_gyp_generator.pro
@@ -25,8 +25,7 @@ RCC_DIR = $$OUT_PWD/$$getConfigDir()/.rcc
# whenever we are cross compiling.
cross_compile: DEFINES += QTWEBENGINE_EMBEDDED_SWITCHES
-contains(QT_CONFIG, egl): CONFIG += egl
-else: DEFINES += QT_NO_EGL
+qtConfig(egl): CONFIG += egl
RESOURCES += devtools.qrc
@@ -75,7 +74,6 @@ SOURCES = \
render_widget_host_view_qt.cpp \
renderer/content_renderer_client_qt.cpp \
renderer/pepper/pepper_flash_browser_host_qt.cpp \
- renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp \
renderer/pepper/pepper_flash_renderer_host_qt.cpp \
renderer/pepper/pepper_host_factory_qt.cpp \
renderer/pepper/pepper_isolated_file_system_message_filter.cpp \
@@ -143,6 +141,7 @@ HEADERS = \
file_picker_controller.h \
gl_context_qt.h \
gl_surface_qt.h \
+ global_descriptors_qt.h \
javascript_dialog_controller_p.h \
javascript_dialog_controller.h \
javascript_dialog_manager_qt.h \
@@ -158,7 +157,6 @@ HEADERS = \
render_widget_host_view_qt_delegate.h \
renderer/content_renderer_client_qt.h \
renderer/pepper/pepper_flash_browser_host_qt.h \
- renderer/pepper/pepper_flash_clipboard_message_filter_qt.h \
renderer/pepper/pepper_flash_renderer_host_qt.h \
renderer/pepper/pepper_host_factory_qt.h \
renderer/pepper/pepper_isolated_file_system_message_filter.h \
@@ -198,3 +196,8 @@ qtHaveModule(positioning) {
HEADERS += location_provider_qt.h
DEFINES += QT_USE_POSITIONING=1
}
+
+qtHaveModule(printsupport) {
+ SOURCES += pdfium_printing_wrapper_qt.cpp
+ HEADERS += pdfium_printing_wrapper_qt.h
+}
diff --git a/src/core/core_module.pro b/src/core/core_module.pro
index 3b9dab457..65e46dcec 100644
--- a/src/core/core_module.pro
+++ b/src/core/core_module.pro
@@ -40,9 +40,9 @@ win32-msvc* {
# and doesn't let Chromium get access to libc symbols through dlsym.
CONFIG -= bsymbolic_functions
-contains(QT_CONFIG, egl): CONFIG += egl
+qtConfig(egl): CONFIG += egl
-linux: contains(QT_CONFIG, separate_debug_info): QMAKE_POST_LINK="cd $(DESTDIR) && $(STRIP) --strip-unneeded $(TARGET)"
+linux:qtConfig(separate_debug_info): QMAKE_POST_LINK="cd $(DESTDIR) && $(STRIP) --strip-unneeded $(TARGET)"
REPACK_DIR = $$OUT_PWD/$$getConfigDir()/gen/repack
# Duplicated from resources/resources.gyp
@@ -58,7 +58,7 @@ resources.files = $$REPACK_DIR/qtwebengine_resources.pak \
icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat
!debug_and_release|!build_all|CONFIG(release, debug|release) {
- contains(QT_CONFIG, qt_framework) {
+ qtConfig(framework) {
locales.version = Versions
locales.path = Resources/qtwebengine_locales
resources.version = Versions
@@ -83,7 +83,7 @@ icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat
}
}
- !contains(QT_CONFIG, qt_framework):!force_independent {
+ !qtConfig(framework):!force_independent {
#
# Copy essential files to the qtbase build directory for non-prefix builds
#
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index 8d0b8166a..3d147226d 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -59,7 +59,6 @@
#include "cc/output/delegated_frame_data.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/draw_quad.h"
-#include "cc/quads/io_surface_draw_quad.h"
#include "cc/quads/render_pass_draw_quad.h"
#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/stream_video_draw_quad.h"
@@ -73,11 +72,18 @@
#include <QOpenGLContext>
#include <QOpenGLFunctions>
-#include <QSGSimpleRectNode>
-#include <QSGSimpleTextureNode>
+#include <QSGFlatColorMaterial>
#include <QSGTexture>
#include <private/qsgadaptationlayer_p.h>
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
+#include <QSGImageNode>
+#include <QSGRectangleNode>
+#else
+#include <QSGSimpleRectNode>
+#include <QSGSimpleTextureNode>
+#endif
+
#if !defined(QT_NO_EGL)
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -196,22 +202,22 @@ static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState
return layerChain;
}
-static void waitChromiumSync(gfx::TransferableFence *sync)
+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 gfx::TransferableFence::NoSync:
+ case gl::TransferableFence::NoSync:
break;
- case gfx::TransferableFence::EglSync:
+ case gl::TransferableFence::EglSync:
#ifdef EGL_KHR_reusable_sync
{
static bool resolved = false;
static PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR = 0;
if (!resolved) {
- if (gfx::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync")) {
+ if (gl::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync")) {
QOpenGLContext *context = QOpenGLContext::currentContext();
eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)context->getProcAddress("eglClientWaitSyncKHR");
}
@@ -224,7 +230,7 @@ static void waitChromiumSync(gfx::TransferableFence *sync)
}
#endif
break;
- case gfx::TransferableFence::ArbSync:
+ case gl::TransferableFence::ArbSync:
typedef void (QOPENGLF_APIENTRYP WaitSyncPtr)(GLsync sync, GLbitfield flags, GLuint64 timeout);
static WaitSyncPtr glWaitSync_ = 0;
if (!glWaitSync_) {
@@ -237,22 +243,22 @@ static void waitChromiumSync(gfx::TransferableFence *sync)
}
}
-static void deleteChromiumSync(gfx::TransferableFence *sync)
+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 gfx::TransferableFence::NoSync:
+ case gl::TransferableFence::NoSync:
break;
- case gfx::TransferableFence::EglSync:
+ case gl::TransferableFence::EglSync:
#ifdef EGL_KHR_reusable_sync
{
static bool resolved = false;
static PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = 0;
if (!resolved) {
- if (gfx::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync")) {
+ if (gl::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync")) {
QOpenGLContext *context = QOpenGLContext::currentContext();
eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)context->getProcAddress("eglDestroySyncKHR");
}
@@ -267,7 +273,7 @@ static void deleteChromiumSync(gfx::TransferableFence *sync)
}
#endif
break;
- case gfx::TransferableFence::ArbSync:
+ case gl::TransferableFence::ArbSync:
typedef void (QOPENGLF_APIENTRYP DeleteSyncPtr)(GLsync sync);
static DeleteSyncPtr glDeleteSync_ = 0;
if (!glDeleteSync_) {
@@ -368,7 +374,7 @@ QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, R
if (!texture) {
if (m_resource.is_software) {
Q_ASSERT(apiDelegate);
- scoped_ptr<cc::SharedBitmap> sharedBitmap = content::HostSharedBitmapManager::current()->GetSharedBitmapFromId(m_resource.size, m_resource.mailbox_holder.mailbox);
+ std::unique_ptr<cc::SharedBitmap> sharedBitmap = content::HostSharedBitmapManager::current()->GetSharedBitmapFromId(m_resource.size, 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
@@ -576,8 +582,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
if (!layer)
continue;
- // Only QSGImageNode currently supports QSGLayer textures.
- QSGImageNode *imageNode = apiDelegate->createImageNode();
+ // Only QSGInternalImageNode currently supports QSGLayer textures.
+ QSGInternalImageNode *imageNode = apiDelegate->createImageNode();
imageNode->setTargetRect(toQt(quad->rect));
imageNode->setInnerTargetRect(toQt(quad->rect));
imageNode->setTexture(layer);
@@ -588,8 +594,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad);
ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates);
- QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
- textureNode->setTextureCoordinatesTransform(tquad->y_flipped ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform);
+ QSGTextureNode *textureNode = apiDelegate->createTextureNode();
+ textureNode->setTextureCoordinatesTransform(tquad->y_flipped ? QSGTextureNode::MirrorVertically : QSGTextureNode::NoTransform);
textureNode->setRect(toQt(quad->rect));
textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate));
@@ -597,7 +603,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
break;
} case cc::DrawQuad::SOLID_COLOR: {
const cc::SolidColorDrawQuad *scquad = cc::SolidColorDrawQuad::MaterialCast(quad);
- QSGSimpleRectNode *rectangleNode = new QSGSimpleRectNode;
+ QSGRectangleNode *rectangleNode = apiDelegate->createRectangleNode();
// Qt only supports MSAA and this flag shouldn't be needed.
// If we ever want to use QSGRectangleNode::setAntialiasing for this we should
@@ -636,7 +642,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad);
ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates);
- QSGSimpleTextureNode *textureNode = new QSGSimpleTextureNode;
+ QSGTextureNode *textureNode = apiDelegate->createTextureNode();
textureNode->setRect(toQt(quad->rect));
textureNode->setSourceRect(toQt(tquad->tex_coord_rect));
textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
@@ -658,13 +664,16 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
initAndHoldTexture(uResource, quad->ShouldDrawWithBlending()),
initAndHoldTexture(vResource, quad->ShouldDrawWithBlending()),
aResource ? initAndHoldTexture(aResource, quad->ShouldDrawWithBlending()) : 0,
- toQt(vquad->ya_tex_coord_rect), toQt(vquad->uv_tex_coord_rect),
- toQt(vquad->ya_tex_size), toQt(vquad->uv_tex_size), toQt(vquad->color_space));
+ toQt(vquad->ya_tex_coord_rect), toQt(vquad->uv_tex_coord_rect),
+ toQt(vquad->ya_tex_size), toQt(vquad->uv_tex_size),
+ toQt(vquad->color_space),
+ vquad->resource_multiplier, vquad->resource_offset);
videoNode->setRect(toQt(quad->rect));
currentLayerChain->appendChildNode(videoNode);
break;
+ }
#ifdef GL_OES_EGL_image_external
- } case cc::DrawQuad::STREAM_VIDEO_CONTENT: {
+ case cc::DrawQuad::STREAM_VIDEO_CONTENT: {
const cc::StreamVideoDrawQuad *squad = cc::StreamVideoDrawQuad::MaterialCast(quad);
ResourceHolder *resource = findAndHoldResource(squad->resource_id(), resourceCandidates);
MailboxTexture *texture = static_cast<MailboxTexture *>(initAndHoldTexture(resource, quad->ShouldDrawWithBlending()));
@@ -675,23 +684,10 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
svideoNode->setTextureMatrix(toQt(squad->matrix.matrix()));
currentLayerChain->appendChildNode(svideoNode);
break;
-#endif
- }
- case cc::DrawQuad::IO_SURFACE_CONTENT: {
- const cc::IOSurfaceDrawQuad *ioquad = cc::IOSurfaceDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(ioquad->io_surface_resource_id(), resourceCandidates);
- MailboxTexture *texture = static_cast<MailboxTexture *>(initAndHoldTexture(resource, quad->ShouldDrawWithBlending()));
- texture->setTarget(GL_TEXTURE_RECTANGLE);
-
- bool flip = ioquad->orientation != cc::IOSurfaceDrawQuad::FLIPPED;
- StreamVideoNode *svideoNode = new StreamVideoNode(texture, flip, RectangleTarget);
- QMatrix4x4 matrix;
- matrix.scale(ioquad->io_surface_size.width(), ioquad->io_surface_size.height());
- svideoNode->setRect(toQt(ioquad->rect));
- svideoNode->setTextureMatrix(matrix);
- currentLayerChain->appendChildNode(svideoNode);
- break;
}
+#endif
+ case cc::DrawQuad::SURFACE_CONTENT:
+ Q_UNREACHABLE();
default:
qWarning("Unimplemented quad material: %d", quad->material);
}
@@ -727,7 +723,7 @@ QSGTexture *DelegatedFrameNode::initAndHoldTexture(ResourceHolder *resource, boo
void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxesToFetch)
{
- QList<gfx::TransferableFence> transferredFences;
+ QList<gl::TransferableFence> transferredFences;
{
QMutexLocker lock(&m_mutex);
@@ -759,7 +755,7 @@ void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxe
m_textureFences.swap(transferredFences);
}
- Q_FOREACH (gfx::TransferableFence sync, transferredFences) {
+ Q_FOREACH (gl::TransferableFence sync, 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.
@@ -832,9 +828,9 @@ void DelegatedFrameNode::pullTexture(DelegatedFrameNode *frameNode, MailboxTextu
if (syncToken.HasData())
mailboxManager->PullTextureUpdates(syncToken);
texture->fetchTexture(mailboxManager);
- if (!!gfx::GLContext::GetCurrent() && gfx::GLFence::IsSupported()) {
+ if (!!gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) {
// Create a fence on the Chromium GPU-thread and context
- gfx::GLFence *fence = gfx::GLFence::Create();
+ 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());
delete fence;
diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h
index 005f4c768..36ec20f1d 100644
--- a/src/core/delegated_frame_node.h
+++ b/src/core/delegated_frame_node.h
@@ -40,7 +40,6 @@
#ifndef DELEGATED_FRAME_NODE_H
#define DELEGATED_FRAME_NODE_H
-#include "base/memory/scoped_ptr.h"
#include "cc/quads/render_pass.h"
#include "cc/resources/transferable_resource.h"
#include "gpu/command_buffer/service/sync_point_manager.h"
@@ -74,7 +73,7 @@ class ChromiumCompositorData : public QSharedData {
public:
ChromiumCompositorData() : frameDevicePixelRatio(1) { }
QHash<unsigned, QSharedPointer<ResourceHolder> > resourceHolders;
- scoped_ptr<cc::DelegatedFrameData> frameData;
+ std::unique_ptr<cc::DelegatedFrameData> frameData;
qreal frameDevicePixelRatio;
};
@@ -104,8 +103,8 @@ private:
int m_numPendingSyncPoints;
QWaitCondition m_mailboxesFetchedWaitCond;
QMutex m_mutex;
- QList<gfx::TransferableFence> m_textureFences;
- scoped_ptr<gpu::SyncPointClient> m_syncPointClient;
+ QList<gl::TransferableFence> m_textureFences;
+ std::unique_ptr<gpu::SyncPointClient> m_syncPointClient;
#if defined(USE_X11)
bool m_contextShared;
QScopedPointer<QOffscreenSurface> m_offsurface;
diff --git a/src/core/desktop_screen_qt.cpp b/src/core/desktop_screen_qt.cpp
index 0904aec59..f18a27ed7 100644
--- a/src/core/desktop_screen_qt.cpp
+++ b/src/core/desktop_screen_qt.cpp
@@ -39,6 +39,9 @@
#include "desktop_screen_qt.h"
+#include "ui/display/display.h"
+#include "ui/gfx/geometry/point.h"
+
namespace QtWebEngineCore {
gfx::Point DesktopScreenQt::GetCursorScreenPoint()
@@ -47,10 +50,10 @@ gfx::Point DesktopScreenQt::GetCursorScreenPoint()
return gfx::Point();
}
-gfx::NativeWindow DesktopScreenQt::GetWindowUnderCursor()
+bool DesktopScreenQt::IsWindowUnderCursor(gfx::NativeWindow)
{
Q_UNREACHABLE();
- return gfx::NativeWindow();
+ return false;
}
gfx::NativeWindow DesktopScreenQt::GetWindowAtScreenPoint(const gfx::Point& point)
@@ -65,42 +68,42 @@ int DesktopScreenQt::GetNumDisplays() const
return 0;
}
-std::vector<gfx::Display> DesktopScreenQt::GetAllDisplays() const
+std::vector<display::Display> DesktopScreenQt::GetAllDisplays() const
{
Q_UNREACHABLE();
- return std::vector<gfx::Display>();
+ return std::vector<display::Display>();
}
-gfx::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeView window) const
+display::Display DesktopScreenQt::GetDisplayNearestWindow(gfx::NativeView window) const
{
// RenderViewHostImpl::OnStartDragging uses this to determine
// the scale factor for the view.
- return gfx::Display();
+ return display::Display();
}
-gfx::Display DesktopScreenQt::GetDisplayNearestPoint(const gfx::Point& point) const
+display::Display DesktopScreenQt::GetDisplayNearestPoint(const gfx::Point& point) const
{
Q_UNREACHABLE();
- return gfx::Display();
+ return display::Display();
}
-gfx::Display DesktopScreenQt::GetDisplayMatching(const gfx::Rect& match_rect) const
+display::Display DesktopScreenQt::GetDisplayMatching(const gfx::Rect& match_rect) const
{
Q_UNREACHABLE();
- return gfx::Display();
+ return display::Display();
}
-gfx::Display DesktopScreenQt::GetPrimaryDisplay() const
+display::Display DesktopScreenQt::GetPrimaryDisplay() const
{
- return gfx::Display();
+ return display::Display();
}
-void DesktopScreenQt::AddObserver(gfx::DisplayObserver* observer)
+void DesktopScreenQt::AddObserver(display::DisplayObserver* observer)
{
Q_UNREACHABLE();
}
-void DesktopScreenQt::RemoveObserver(gfx::DisplayObserver* observer)
+void DesktopScreenQt::RemoveObserver(display::DisplayObserver* observer)
{
Q_UNREACHABLE();
}
diff --git a/src/core/desktop_screen_qt.h b/src/core/desktop_screen_qt.h
index ec7fe2e32..0e7588ae2 100644
--- a/src/core/desktop_screen_qt.h
+++ b/src/core/desktop_screen_qt.h
@@ -40,26 +40,26 @@
#ifndef DESKTOP_SCREEN_QT_H
#define DESKTOP_SCREEN_QT_H
-#include "ui/gfx/screen.h"
+#include "ui/display/screen.h"
#include <QtGlobal>
namespace QtWebEngineCore {
-class DesktopScreenQt : public gfx::Screen {
+class DesktopScreenQt : public display::Screen {
public:
// Overridden from gfx::Screen:
virtual gfx::Point GetCursorScreenPoint() Q_DECL_OVERRIDE;
- virtual gfx::NativeWindow GetWindowUnderCursor() Q_DECL_OVERRIDE;
+ virtual bool IsWindowUnderCursor(gfx::NativeWindow) Q_DECL_OVERRIDE;
virtual gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) Q_DECL_OVERRIDE;
virtual int GetNumDisplays() const Q_DECL_OVERRIDE;
- virtual std::vector<gfx::Display> GetAllDisplays() const Q_DECL_OVERRIDE;
- virtual gfx::Display GetDisplayNearestWindow(gfx::NativeView window) const Q_DECL_OVERRIDE;
- virtual gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const Q_DECL_OVERRIDE;
- virtual gfx::Display GetDisplayMatching(const gfx::Rect& match_rect) const Q_DECL_OVERRIDE;
- virtual gfx::Display GetPrimaryDisplay() const Q_DECL_OVERRIDE;
- virtual void AddObserver(gfx::DisplayObserver* observer) Q_DECL_OVERRIDE;
- virtual void RemoveObserver(gfx::DisplayObserver* observer) Q_DECL_OVERRIDE;
+ virtual std::vector<display::Display> GetAllDisplays() const Q_DECL_OVERRIDE;
+ virtual display::Display GetDisplayNearestWindow(gfx::NativeView window) const Q_DECL_OVERRIDE;
+ virtual display::Display GetDisplayNearestPoint(const gfx::Point& point) const Q_DECL_OVERRIDE;
+ virtual display::Display GetDisplayMatching(const gfx::Rect& match_rect) const Q_DECL_OVERRIDE;
+ virtual display::Display GetPrimaryDisplay() const Q_DECL_OVERRIDE;
+ virtual void AddObserver(display::DisplayObserver* observer) Q_DECL_OVERRIDE;
+ virtual void RemoveObserver(display::DisplayObserver* observer) Q_DECL_OVERRIDE;
};
} // namespace QtWebEngineCore
diff --git a/src/core/dev_tools_http_handler_delegate_qt.cpp b/src/core/dev_tools_http_handler_delegate_qt.cpp
index f3ffcc86d..5fd35ee29 100644
--- a/src/core/dev_tools_http_handler_delegate_qt.cpp
+++ b/src/core/dev_tools_http_handler_delegate_qt.cpp
@@ -50,6 +50,7 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/devtools_discovery/devtools_discovery_manager.h"
@@ -85,10 +86,10 @@ public:
: m_address(address), m_port(port), m_backlog(backlog)
{}
private:
- scoped_ptr<net::ServerSocket> CreateForHttpServer() override {
- scoped_ptr<net::ServerSocket> socket(new net::TCPServerSocket(nullptr, net::NetLog::Source()));
+ std::unique_ptr<net::ServerSocket> CreateForHttpServer() override {
+ std::unique_ptr<net::ServerSocket> socket(new net::TCPServerSocket(nullptr, net::NetLog::Source()));
if (socket->ListenWithAddressAndPort(m_address, m_port, m_backlog) != net::OK)
- return scoped_ptr<net::ServerSocket>();
+ return std::unique_ptr<net::ServerSocket>();
return socket;
}
@@ -178,18 +179,18 @@ DevToolsTargetDescriptor::List DevToolsDiscoveryProviderQt::GetDescriptors()
namespace QtWebEngineCore {
-scoped_ptr<DevToolsHttpHandler> createDevToolsHttpHandler()
+std::unique_ptr<DevToolsHttpHandler> createDevToolsHttpHandler()
{
DevToolsHttpHandlerDelegateQt *delegate = new DevToolsHttpHandlerDelegateQt();
if (!delegate->isValid()) {
delete delegate;
return nullptr;
}
- scoped_ptr<DevToolsHttpHandler::ServerSocketFactory> factory(new TCPServerSocketFactory(delegate->bindAddress().toStdString(), delegate->port(), 1));
+ std::unique_ptr<DevToolsHttpHandler::ServerSocketFactory> factory(new TCPServerSocketFactory(delegate->bindAddress().toStdString(), delegate->port(), 1));
// Ownership of the delegate is taken over the devtools http handler.
- scoped_ptr<DevToolsHttpHandler> handler(new DevToolsHttpHandler(std::move(factory), std::string(), delegate, base::FilePath(), base::FilePath(), std::string(), std::string()));
- DevToolsDiscoveryManager::GetInstance()->AddProvider(scoped_ptr<DevToolsDiscoveryManager::Provider>(new DevToolsDiscoveryProviderQt()));
- return handler;
+ std::unique_ptr<DevToolsHttpHandler> handler(new DevToolsHttpHandler(std::move(factory), std::string(), delegate, base::FilePath(), base::FilePath(), std::string(), std::string()));
+ DevToolsDiscoveryManager::GetInstance()->AddProvider(base::WrapUnique(new DevToolsDiscoveryProviderQt()));
+ return std::move(handler);
}
DevToolsHttpHandlerDelegateQt::DevToolsHttpHandlerDelegateQt()
diff --git a/src/core/dev_tools_http_handler_delegate_qt.h b/src/core/dev_tools_http_handler_delegate_qt.h
index 96a34a45a..6512146a5 100644
--- a/src/core/dev_tools_http_handler_delegate_qt.h
+++ b/src/core/dev_tools_http_handler_delegate_qt.h
@@ -56,7 +56,7 @@ class DevToolsHttpHandler;
namespace QtWebEngineCore {
-scoped_ptr<devtools_http_handler::DevToolsHttpHandler> createDevToolsHttpHandler();
+std::unique_ptr<devtools_http_handler::DevToolsHttpHandler> createDevToolsHttpHandler();
class DevToolsHttpHandlerDelegateQt : public devtools_http_handler::DevToolsHttpHandlerDelegate {
public:
diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp
index 857af2e18..2cbfd121b 100644
--- a/src/core/download_manager_delegate_qt.cpp
+++ b/src/core/download_manager_delegate_qt.cpp
@@ -56,6 +56,7 @@
#include "browser_context_adapter_client.h"
#include "browser_context_qt.h"
#include "type_conversion.h"
+#include "web_contents_delegate_qt.h"
#include "qtwebenginecoreglobal.h"
namespace QtWebEngineCore {
@@ -74,6 +75,7 @@ DownloadManagerDelegateQt::DownloadManagerDelegateQt(BrowserContextAdapter *cont
: m_contextAdapter(contextAdapter)
, m_currentId(0)
, m_weakPtrFactory(this)
+ , m_downloadType(BrowserContextAdapterClient::Attachment)
{
Q_ASSERT(m_contextAdapter);
}
@@ -115,6 +117,11 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i
QString suggestedFilename = toQt(item->GetSuggestedFilename());
QString mimeTypeString = toQt(item->GetMimeType());
+ bool isAttachment = net::HttpContentDisposition(item->GetContentDisposition(), std::string()).is_attachment();
+
+ if (!isAttachment || !BrowserContextAdapterClient::UserRequested)
+ m_downloadType = BrowserContextAdapterClient::DownloadAttribute;
+
if (suggestedFilename.isEmpty())
suggestedFilename = toQt(net::HttpContentDisposition(item->GetContentDisposition(), std::string()).filename());
@@ -157,7 +164,8 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(content::DownloadItem* i
mimeTypeString,
suggestedFilePath,
BrowserContextAdapterClient::UnknownSavePageFormat,
- false /* accepted */
+ false /* accepted */,
+ m_downloadType
};
Q_FOREACH (BrowserContextAdapterClient *client, clients) {
@@ -211,12 +219,30 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content
if (clients.isEmpty())
return;
- const QString suggestedFileName
- = QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName()
- + QStringLiteral(".mhtml");
- const QDir defaultDownloadDirectory
- = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
- const QString suggestedFilePath = defaultDownloadDirectory.absoluteFilePath(suggestedFileName);
+ WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
+ web_contents->GetDelegate());
+ const SavePageInfo &spi = contentsDelegate->savePageInfo();
+
+ bool acceptedByDefault = false;
+ QString suggestedFilePath = spi.requestedFilePath;
+ if (suggestedFilePath.isEmpty()) {
+ suggestedFilePath = QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName()
+ + QStringLiteral(".mhtml");
+ } else {
+ acceptedByDefault = true;
+ }
+ if (QFileInfo(suggestedFilePath).isRelative()) {
+ const QDir downloadDir(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
+ suggestedFilePath = downloadDir.absoluteFilePath(suggestedFilePath);
+ }
+
+ BrowserContextAdapterClient::SavePageFormat suggestedSaveFormat
+ = static_cast<BrowserContextAdapterClient::SavePageFormat>(spi.requestedFormat);
+ if (suggestedSaveFormat == BrowserContextAdapterClient::UnknownSavePageFormat)
+ suggestedSaveFormat = BrowserContextAdapterClient::MimeHtmlSaveFormat;
+
+ // Clear the delegate's SavePageInfo. It's only valid for the page currently being saved.
+ contentsDelegate->setSavePageInfo(SavePageInfo());
BrowserContextAdapterClient::DownloadItemInfo info = {
m_currentId + 1,
@@ -226,8 +252,9 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content
0, /* receivedBytes */
QStringLiteral("application/x-mimearchive"),
suggestedFilePath,
- BrowserContextAdapterClient::MimeHtmlSaveFormat,
- false /* accepted */
+ suggestedSaveFormat,
+ acceptedByDefault,
+ BrowserContextAdapterClient::SavePage
};
Q_FOREACH (BrowserContextAdapterClient *client, clients) {
@@ -263,7 +290,8 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(content::DownloadItem *downloa
toQt(download->GetMimeType()),
QString(),
BrowserContextAdapterClient::UnknownSavePageFormat,
- true /* accepted */
+ true /* accepted */,
+ m_downloadType
};
Q_FOREACH (BrowserContextAdapterClient *client, clients) {
diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h
index e724b4e23..e603724e9 100644
--- a/src/core/download_manager_delegate_qt.h
+++ b/src/core/download_manager_delegate_qt.h
@@ -82,9 +82,10 @@ public:
bool can_save_as_complete,
const content::SavePackagePathPickedCallback &callback) Q_DECL_OVERRIDE;
-
void cancelDownload(quint32 downloadId);
+ void setDownloadType(int downloadType) { m_downloadType = downloadType; }
+
// Inherited from content::DownloadItem::Observer
void OnDownloadUpdated(content::DownloadItem *download) Q_DECL_OVERRIDE;
void OnDownloadDestroyed(content::DownloadItem *download) Q_DECL_OVERRIDE;
@@ -96,6 +97,7 @@ private:
uint64_t m_currentId;
base::WeakPtrFactory<DownloadManagerDelegateQt> m_weakPtrFactory;
+ int m_downloadType;
friend class DownloadManagerDelegateInstance;
DISALLOW_COPY_AND_ASSIGN(DownloadManagerDelegateQt);
diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp
index 6c3889907..74b097ef6 100644
--- a/src/core/file_picker_controller.cpp
+++ b/src/core/file_picker_controller.cpp
@@ -111,20 +111,20 @@ void FilePickerController::filesSelectedInChooser(const QStringList &filesList,
if (this->m_mode == UploadFolder && !filesList.isEmpty()
&& QFileInfo(filesList.first()).isDir()) // Enumerate the directory
files = listRecursively(QDir(filesList.first()));
- rvh->FilesSelectedInChooser(toVector<content::FileChooserFileInfo>(files), static_cast<content::FileChooserParams::Mode>(this->m_mode));
+ rvh->GetMainFrame()->FilesSelectedInChooser(toVector<content::FileChooserFileInfo>(files), static_cast<content::FileChooserParams::Mode>(this->m_mode));
}
-QStringList FilePickerController::acceptedMimeTypes()
+QStringList FilePickerController::acceptedMimeTypes() const
{
return m_acceptedMimeTypes;
}
-FilePickerController::FileChooserMode FilePickerController::mode()
+FilePickerController::FileChooserMode FilePickerController::mode() const
{
return m_mode;
}
-QString FilePickerController::defaultFileName()
+QString FilePickerController::defaultFileName() const
{
return m_defaultFileName;
}
diff --git a/src/core/file_picker_controller.h b/src/core/file_picker_controller.h
index 6edee7713..14e8de42d 100644
--- a/src/core/file_picker_controller.h
+++ b/src/core/file_picker_controller.h
@@ -61,10 +61,9 @@ public:
};
FilePickerController(FileChooserMode mode, content::WebContents *contents, const QString &defaultFileName, const QStringList &acceptedMimeTypes, QObject * = 0);
- QStringList acceptedMimeTypes();
- QString defaultFileName();
- FileChooserMode mode();
- void filesSelectedInChooser(const QStringList &filesList, content::WebContents *contents);
+ QStringList acceptedMimeTypes() const;
+ QString defaultFileName() const;
+ FileChooserMode mode() const;
public Q_SLOTS:
void accepted(const QStringList &files);
@@ -72,6 +71,7 @@ public Q_SLOTS:
void rejected();
private:
+ void filesSelectedInChooser(const QStringList &filesList, content::WebContents *contents);
QString m_defaultFileName;
QStringList m_acceptedMimeTypes;
content::WebContents *m_contents;
diff --git a/src/core/gl_context_qt.cpp b/src/core/gl_context_qt.cpp
index 0cf873631..bbcd3554d 100644
--- a/src/core/gl_context_qt.cpp
+++ b/src/core/gl_context_qt.cpp
@@ -89,19 +89,19 @@ void GLContextHelper::destroy()
contextHelper = 0;
}
-bool GLContextHelper::initializeContextOnBrowserThread(gfx::GLContext* context, gfx::GLSurface* surface)
+bool GLContextHelper::initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface)
{
- return context->Initialize(surface, gfx::PreferDiscreteGpu);
+ return context->Initialize(surface, gl::PreferDiscreteGpu);
}
-bool GLContextHelper::initializeContext(gfx::GLContext* context, gfx::GLSurface* surface)
+bool GLContextHelper::initializeContext(gl::GLContext* context, gl::GLSurface* surface)
{
bool ret = false;
Qt::ConnectionType connType = (QThread::currentThread() == qApp->thread()) ? Qt::DirectConnection : Qt::BlockingQueuedConnection;
QMetaObject::invokeMethod(contextHelper, "initializeContextOnBrowserThread", connType,
Q_RETURN_ARG(bool, ret),
- Q_ARG(gfx::GLContext*, context),
- Q_ARG(gfx::GLSurface*, surface));
+ Q_ARG(gl::GLContext*, context),
+ Q_ARG(gl::GLSurface*, surface));
return ret;
}
@@ -143,9 +143,11 @@ QT_END_NAMESPACE
#if defined(USE_OZONE) || defined(OS_WIN)
-namespace gfx {
+namespace gl {
-scoped_refptr<GLContext> GLContext::CreateGLContext(GLShareGroup* share_group, GLSurface* compatible_surface, GpuPreference gpu_preference)
+namespace init {
+
+scoped_refptr<GLContext> CreateGLContext(GLShareGroup* share_group, GLSurface* compatible_surface, GpuPreference gpu_preference)
{
#if defined(OS_WIN)
scoped_refptr<GLContext> context;
@@ -167,6 +169,8 @@ scoped_refptr<GLContext> GLContext::CreateGLContext(GLShareGroup* share_group, G
return context;
}
-} // namespace gfx
+} // namespace init
+
+} // namespace gl
#endif // defined(USE_OZONE) || defined(OS_WIN)
diff --git a/src/core/gl_context_qt.h b/src/core/gl_context_qt.h
index 2c04641d4..47cd7dc7f 100644
--- a/src/core/gl_context_qt.h
+++ b/src/core/gl_context_qt.h
@@ -42,7 +42,7 @@
#include <QObject>
-namespace gfx {
+namespace gl {
class GLContext;
class GLSurface;
}
@@ -54,7 +54,7 @@ class GLContextHelper : public QObject {
public:
static void initialize();
static void destroy();
- static bool initializeContext(gfx::GLContext* context, gfx::GLSurface* surface);
+ static bool initializeContext(gl::GLContext* context, gl::GLSurface* surface);
static void* getEGLConfig();
static void* getXConfig();
@@ -63,7 +63,7 @@ public:
static void* getNativeDisplay();
private:
- Q_INVOKABLE bool initializeContextOnBrowserThread(gfx::GLContext* context, gfx::GLSurface* surface);
+ Q_INVOKABLE bool initializeContextOnBrowserThread(gl::GLContext* context, gl::GLSurface* surface);
static GLContextHelper* contextHelper;
};
diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp
index f499d853e..e88a26715 100644
--- a/src/core/gl_surface_qt.cpp
+++ b/src/core/gl_surface_qt.cpp
@@ -50,12 +50,13 @@
#include "qtwebenginecoreglobal_p.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/gpu/image_transport_surface.h"
+#include "gpu/ipc/service/image_transport_surface.h"
#include "ui/gl/egl_util.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/init/gl_initializer.h"
+#include "ui/gl/init/gl_factory.h"
#if defined(USE_X11)
#include "ui/gl/gl_surface_glx.h"
@@ -68,6 +69,7 @@ extern "C" {
#if defined(OS_WIN)
#include "ui/gl/gl_surface_wgl.h"
#include "ui/gl/gl_context_wgl.h"
+#include "ui/gl/vsync_provider_win.h"
#endif
// From ANGLE's egl/eglext.h.
@@ -78,7 +80,7 @@ extern "C" {
using ui::GetLastEGLErrorString;
-namespace gfx {
+namespace gl {
namespace {
@@ -310,7 +312,7 @@ bool GLSurfaceQtWGL::Initialize()
{
m_surfaceBuffer = new PbufferGLSurfaceWGL(m_size);
- return m_surfaceBuffer->Initialize();
+ return m_surfaceBuffer->Initialize(gl::GLSurface::SURFACE_DEFAULT);
}
void GLSurfaceQtWGL::Destroy()
@@ -365,8 +367,8 @@ bool GLSurfaceQtEGL::InitializeOneOff()
g_egl_surfaceless_context_supported = ExtensionsContain(g_extensions, "EGL_KHR_surfaceless_context");
if (g_egl_surfaceless_context_supported) {
- scoped_refptr<GLSurface> surface = new GLSurfacelessQtEGL(Size(1, 1));
- scoped_refptr<GLContext> context = GLContext::CreateGLContext(
+ scoped_refptr<GLSurface> surface = new GLSurfacelessQtEGL(gfx::Size(1, 1));
+ scoped_refptr<GLContext> context = init::CreateGLContext(
NULL, surface.get(), PreferIntegratedGpu);
if (!context->MakeCurrent(surface.get()))
@@ -384,25 +386,6 @@ bool GLSurfaceQtEGL::InitializeOneOff()
return true;
}
-bool GLSurface::InitializeOneOffInternal()
-{
- if (GetGLImplementation() == kGLImplementationOSMesaGL)
- return false;
-
- if (GetGLImplementation() == kGLImplementationEGLGLES2)
- return GLSurfaceQtEGL::InitializeOneOff();
-
- if (GetGLImplementation() == kGLImplementationDesktopGL) {
-#if defined(USE_X11)
- return GLSurfaceQtGLX::InitializeOneOff();
-#elif defined(OS_WIN)
- return GLSurfaceQtWGL::InitializeOneOff();
-#endif
- }
-
- return false;
-}
-
EGLDisplay GLSurfaceEGL::GetHardwareDisplay()
{
return static_cast<EGLDisplay>(g_display);
@@ -575,11 +558,36 @@ void* GLSurfacelessQtEGL::GetShareHandle()
return NULL;
}
-// static
+namespace init {
+
+bool InitializeGLOneOffPlatform()
+{
+#if defined(OS_WIN)
+ VSyncProviderWin::InitializeOneOff();
+#endif
+
+ if (GetGLImplementation() == kGLImplementationOSMesaGL)
+ return false;
+
+ if (GetGLImplementation() == kGLImplementationEGLGLES2)
+ return GLSurfaceQtEGL::InitializeOneOff();
+
+ if (GetGLImplementation() == kGLImplementationDesktopGL) {
+#if defined(USE_X11)
+ return GLSurfaceQtGLX::InitializeOneOff();
+#elif defined(OS_WIN)
+ return GLSurfaceQtWGL::InitializeOneOff();
+#endif
+ }
+
+ return false;
+}
+
scoped_refptr<GLSurface>
-GLSurface::CreateOffscreenGLSurface(const gfx::Size& size)
+CreateOffscreenGLSurface(const gfx::Size& size)
{
switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGLCoreProfile:
case kGLImplementationDesktopGL: {
#if defined(USE_X11)
scoped_refptr<GLSurface> surface = new GLSurfaceQtGLX(size);
@@ -614,14 +622,15 @@ GLSurface::CreateOffscreenGLSurface(const gfx::Size& size)
}
}
-// static
scoped_refptr<GLSurface>
-GLSurface::CreateViewGLSurface(gfx::AcceleratedWidget window)
+CreateViewGLSurface(gfx::AcceleratedWidget window)
{
QT_NOT_USED
return NULL;
}
+} // namespace init
+
std::string DriverEGL::GetPlatformExtensions()
{
EGLDisplay display = GLContextHelper::getEGLDisplay();
@@ -633,15 +642,16 @@ std::string DriverEGL::GetPlatformExtensions()
return str ? std::string(str) : "";
}
-} // namespace gfx
+} // namespace gl
-namespace content {
+namespace gpu {
class GpuCommandBufferStub;
class GpuChannelManager;
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(GpuChannelManager*, GpuCommandBufferStub*, const gfx::GLSurfaceHandle&)
+scoped_refptr<gl::GLSurface> ImageTransportSurface::CreateNativeSurface(GpuChannelManager*, GpuCommandBufferStub*,
+ SurfaceHandle, gl::GLSurface::Format)
{
QT_NOT_USED
- return scoped_refptr<gfx::GLSurface>();
+ return scoped_refptr<gl::GLSurface>();
}
}
diff --git a/src/core/gl_surface_qt.h b/src/core/gl_surface_qt.h
index 33ea2a1da..9e0692c60 100644
--- a/src/core/gl_surface_qt.h
+++ b/src/core/gl_surface_qt.h
@@ -47,7 +47,7 @@
#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE
-namespace gfx {
+namespace gl {
class GLSurfaceQt: public GLSurface {
public:
diff --git a/src/core/global_descriptors_qt.h b/src/core/global_descriptors_qt.h
new file mode 100644
index 000000000..e9d490a2e
--- /dev/null
+++ b/src/core/global_descriptors_qt.h
@@ -0,0 +1,10 @@
+#ifndef GLOBAL_DESCRIPTORS_QT_H
+#define GLOBAL_DESCRIPTORS_QT_H
+
+#include "content/public/common/content_descriptors.h"
+
+enum {
+ kWebEngineLocale = kContentIPCDescriptorMax + 1,
+};
+
+#endif // GLOBAL_DESCRIPTORS_QT_H
diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro
index 98ff29f78..9f2a44d7b 100644
--- a/src/core/gyp_run.pro
+++ b/src/core/gyp_run.pro
@@ -24,7 +24,7 @@ GYP_CONFIG += disable_glibcxx_debug=1
!webcore_debug: GYP_CONFIG += remove_webcore_debug_symbols=1
!v8base_debug: GYP_CONFIG += remove_v8base_debug_symbols=1
-linux:contains(QT_CONFIG, separate_debug_info): GYP_CONFIG += linux_dump_symbols=1
+linux:qtConfig(separate_debug_info): GYP_CONFIG += linux_dump_symbols=1
force_debug_info {
win32: GYP_CONFIG += win_release_extra_cflags=-Zi
@@ -36,9 +36,9 @@ force_debug_info {
# Copy this logic from qt_module.prf so that ninja can run according
# to the same rules as the final module linking in core_module.pro.
!host_build:if(win32|mac):!macx-xcode {
- contains(QT_CONFIG, simulator_and_device): CONFIG += simulator_and_device
- contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release
- contains(QT_CONFIG, build_all):CONFIG += build_all
+ qtConfig(simulator_and_device): CONFIG += simulator_and_device
+ qtConfig(debug_and_release): CONFIG += debug_and_release
+ qtConfig(build_all): CONFIG += build_all
}
cross_compile {
@@ -130,7 +130,7 @@ contains(WEBENGINE_CONFIG, no_spellcheck): {
osx: GYP_CONFIG += use_browser_spellchecker=1
}
-!contains(QT_CONFIG, qt_framework): contains(QT_CONFIG, private_tests) {
+!qtConfig(framework):qtConfig(private_tests) {
GYP_CONFIG += qt_install_data=\"$$[QT_INSTALL_DATA/get]\"
GYP_CONFIG += qt_install_translations=\"$$[QT_INSTALL_TRANSLATIONS/get]\"
}
diff --git a/src/core/javascript_dialog_manager_qt.cpp b/src/core/javascript_dialog_manager_qt.cpp
index 80a28fb56..2844dba5d 100644
--- a/src/core/javascript_dialog_manager_qt.cpp
+++ b/src/core/javascript_dialog_manager_qt.cpp
@@ -55,10 +55,8 @@ JavaScriptDialogManagerQt *JavaScriptDialogManagerQt::GetInstance()
return base::Singleton<JavaScriptDialogManagerQt>::get();
}
-void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, const std::string &acceptLang, content::JavaScriptMessageType javascriptMessageType, const base::string16 &messageText, const base::string16 &defaultPromptText, const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage)
+void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webContents, const GURL &originUrl, content::JavaScriptMessageType javascriptMessageType, const base::string16 &messageText, const base::string16 &defaultPromptText, const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage)
{
- Q_UNUSED(acceptLang);
-
WebContentsAdapterClient *client = WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client();
if (!client) {
if (didSuppressMessage)
@@ -70,10 +68,10 @@ void JavaScriptDialogManagerQt::RunJavaScriptDialog(content::WebContents *webCon
runDialogForContents(webContents, dialogType, toQt(messageText).toHtmlEscaped(), toQt(defaultPromptText).toHtmlEscaped(), toQt(originUrl.GetOrigin()), callback);
}
-void JavaScriptDialogManagerQt::RunBeforeUnloadDialog(content::WebContents *webContents, const base::string16 &messageText,
- bool isReload, const content::JavaScriptDialogManager::DialogClosedCallback &callback) {
+void JavaScriptDialogManagerQt::RunBeforeUnloadDialog(content::WebContents *webContents, bool isReload,
+ const content::JavaScriptDialogManager::DialogClosedCallback &callback) {
Q_UNUSED(isReload);
- runDialogForContents(webContents, WebContentsAdapterClient::UnloadDialog, toQt(messageText).toHtmlEscaped(), QString() , QUrl(), callback);
+ runDialogForContents(webContents, WebContentsAdapterClient::UnloadDialog, QString()/*toQt(messageText).toHtmlEscaped()*/, QString() , QUrl(), callback);
}
bool JavaScriptDialogManagerQt::HandleJavaScriptDialog(content::WebContents *contents, bool accept, const base::string16 *promptOverride)
diff --git a/src/core/javascript_dialog_manager_qt.h b/src/core/javascript_dialog_manager_qt.h
index aea5a5ec3..8ed86c994 100644
--- a/src/core/javascript_dialog_manager_qt.h
+++ b/src/core/javascript_dialog_manager_qt.h
@@ -61,12 +61,12 @@ public:
// For use with the Singleton helper class from chromium
static JavaScriptDialogManagerQt *GetInstance();
- virtual void RunJavaScriptDialog(content::WebContents *, const GURL &, const std::string &acceptLang, content::JavaScriptMessageType javascriptMessageType,
- const base::string16 &messageText, const base::string16 &defaultPromptText,
- const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) Q_DECL_OVERRIDE;
+ virtual void RunJavaScriptDialog(content::WebContents *, const GURL &, content::JavaScriptMessageType javascriptMessageType,
+ const base::string16 &messageText, const base::string16 &defaultPromptText,
+ const content::JavaScriptDialogManager::DialogClosedCallback &callback, bool *didSuppressMessage) Q_DECL_OVERRIDE;
- virtual void RunBeforeUnloadDialog(content::WebContents *, const base::string16 &messageText, bool isReload,
- const content::JavaScriptDialogManager::DialogClosedCallback &callback) Q_DECL_OVERRIDE;
+ virtual void RunBeforeUnloadDialog(content::WebContents *, bool isReload,
+ const content::JavaScriptDialogManager::DialogClosedCallback &callback) Q_DECL_OVERRIDE;
virtual bool HandleJavaScriptDialog(content::WebContents *, bool accept, const base::string16 *promptOverride) Q_DECL_OVERRIDE;
virtual void CancelActiveAndPendingDialogs(content::WebContents *contents) Q_DECL_OVERRIDE { takeDialogForContents(contents); }
virtual void ResetDialogState(content::WebContents *contents) Q_DECL_OVERRIDE { takeDialogForContents(contents); }
diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp
index b38e90c69..3e260587c 100644
--- a/src/core/media_capture_devices_dispatcher.cpp
+++ b/src/core/media_capture_devices_dispatcher.cpp
@@ -60,6 +60,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/media_stream_request.h"
+#include "media/audio/audio_device_description.h"
#include "media/audio/audio_manager_base.h"
#include "ui/base/l10n/l10n_util.h"
@@ -89,27 +90,34 @@ base::string16 getContentsUrl(content::WebContents *webContents)
}
// Based on chrome/browser/media/desktop_capture_access_handler.cc:
-scoped_ptr<content::MediaStreamUI> getDevicesForDesktopCapture(content::MediaStreamDevices &devices, content::DesktopMediaID mediaId
+std::unique_ptr<content::MediaStreamUI> getDevicesForDesktopCapture(content::MediaStreamDevices *devices, content::DesktopMediaID mediaId
, bool captureAudio, bool /*display_notification*/, base::string16 /*application_title*/)
{
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- scoped_ptr<content::MediaStreamUI> ui;
-
- // Add selected desktop source to the list.
- devices.push_back(content::MediaStreamDevice(
- content::MEDIA_DESKTOP_VIDEO_CAPTURE, mediaId.ToString(), "Screen"));
- if (captureAudio) {
- devices.push_back(content::MediaStreamDevice(
- content::MEDIA_DESKTOP_AUDIO_CAPTURE,
- media::AudioManagerBase::kLoopbackInputDeviceId, "System Audio"));
- }
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ std::unique_ptr<content::MediaStreamUI> ui;
+
+ // Add selected desktop source to the list.
+ devices->push_back(content::MediaStreamDevice(content::MEDIA_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,
+ 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,
+ media::AudioDeviceDescription::kLoopbackInputDeviceId,
+ "System Audio"));
+ }
+ }
- return std::move(ui);
+ return std::move(ui);
}
WebContentsAdapterClient::MediaRequestFlags mediaRequestFlagsForRequest(const content::MediaStreamRequest &request)
{
- WebContentsAdapterClient::MediaRequestFlags requestFlags;
+ WebContentsAdapterClient::MediaRequestFlags requestFlags = WebContentsAdapterClient::MediaNone;
if (request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE)
requestFlags |= WebContentsAdapterClient::MediaAudioCapture;
if (request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE)
@@ -188,7 +196,7 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content:
BrowserThread::UI, FROM_HERE, base::Bind(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, base::Unretained(this), webContents));
}
- callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, scoped_ptr<content::MediaStreamUI>());
+ callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::unique_ptr<content::MediaStreamUI>());
}
@@ -248,7 +256,7 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::
, const content::MediaResponseCallback &callback)
{
content::MediaStreamDevices devices;
- scoped_ptr<content::MediaStreamUI> ui;
+ std::unique_ptr<content::MediaStreamUI> ui;
if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) {
callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::move(ui));
@@ -289,8 +297,8 @@ void MediaCaptureDevicesDispatcher::processDesktopCaptureAccessRequest(content::
request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE);
ui = getDevicesForDesktopCapture(
- devices, mediaId, capture_audio, true,
- getContentsUrl(webContents));
+ &devices, mediaId, capture_audio, true,
+ getContentsUrl(webContents));
callback.Run(devices, devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE : content::MEDIA_DEVICE_OK, std::move(ui));
}
@@ -317,16 +325,16 @@ void MediaCaptureDevicesDispatcher::processScreenCaptureAccessRequest(content::W
JavaScriptDialogManagerQt::GetInstance()->runDialogForContents(webContents, WebContentsAdapterClient::InternalAuthorizationDialog, message
, QString(), securityOrigin, dialogCallback, title);
} else
- callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_INVALID_STATE, scoped_ptr<content::MediaStreamUI>());
+ callback.Run(content::MediaStreamDevices(), content::MEDIA_DEVICE_INVALID_STATE, std::unique_ptr<content::MediaStreamUI>());
}
void MediaCaptureDevicesDispatcher::handleScreenCaptureAccessRequest(content::WebContents *webContents, bool userAccepted, const base::string16 &)
{
content::MediaStreamDevices devices;
- scoped_ptr<content::MediaStreamUI> ui;
+ std::unique_ptr<content::MediaStreamUI> ui;
if (userAccepted) {
content::DesktopMediaID screenId = content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0);
- ui = getDevicesForDesktopCapture(devices, screenId, false/*capture_audio*/, false/*display_notification*/, getContentsUrl(webContents));
+ ui = getDevicesForDesktopCapture(&devices, screenId, false/*capture_audio*/, false/*display_notification*/, getContentsUrl(webContents));
}
std::map<content::WebContents*, RequestsQueue>::iterator it =
m_pendingRequests.find(webContents);
@@ -417,13 +425,19 @@ void MediaCaptureDevicesDispatcher::OnMediaRequestStateChanged(int render_proces
page_request_id, security_origin, stream_type, state));
}
-void MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread(int render_process_id, int render_frame_id, int page_request_id
- , const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state)
+void MediaCaptureDevicesDispatcher::updateMediaRequestStateOnUIThread(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::UI);
+
// Track desktop capture sessions. Tracking is necessary to avoid unbalanced
// session counts since not all requests will reach MEDIA_REQUEST_STATE_DONE,
// but they will all reach MEDIA_REQUEST_STATE_CLOSING.
- if (stream_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE) {
+ if (stream_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || stream_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
if (state == content::MEDIA_REQUEST_STATE_DONE) {
DesktopCaptureSession session = { render_process_id, render_frame_id,
page_request_id };
diff --git a/src/core/media_capture_devices_dispatcher.h b/src/core/media_capture_devices_dispatcher.h
index b13a9da2c..b21d40b87 100644
--- a/src/core/media_capture_devices_dispatcher.h
+++ b/src/core/media_capture_devices_dispatcher.h
@@ -49,7 +49,6 @@
#include "web_contents_adapter_client.h"
#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/observer_list.h"
#include "content/public/browser/media_observer.h"
@@ -83,6 +82,11 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver,
virtual void OnMediaRequestStateChanged(int render_process_id, int render_frame_id, int page_request_id, const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state) Q_DECL_OVERRIDE;
virtual void OnCreatingAudioStream(int /*render_process_id*/, int /*render_frame_id*/) Q_DECL_OVERRIDE { }
+ virtual void OnSetCapturingLinkSecured(int /*render_process_id*/,
+ int /*render_frame_id*/,
+ int /*page_request_id*/,
+ content::MediaStreamType /*stream_type*/,
+ bool /*is_secure*/) Q_DECL_OVERRIDE { }
DesktopStreamsRegistry *getDesktopStreamsRegistry();
@@ -118,7 +122,7 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver,
RequestsQueues m_pendingRequests;
- scoped_ptr<DesktopStreamsRegistry> m_desktopStreamsRegistry;
+ std::unique_ptr<DesktopStreamsRegistry> m_desktopStreamsRegistry;
content::NotificationRegistrar m_notificationsRegistrar;
diff --git a/src/core/network_delegate_qt.cpp b/src/core/network_delegate_qt.cpp
index ff0e8320c..ed54f2ec8 100644
--- a/src/core/network_delegate_qt.cpp
+++ b/src/core/network_delegate_qt.cpp
@@ -230,24 +230,18 @@ bool NetworkDelegateQt::OnCanSetCookie(const net::URLRequest& request,
return m_requestContextGetter->m_cookieDelegate->canSetCookie(toQt(request.first_party_for_cookies()), QByteArray::fromStdString(cookie_line), toQt(request.url()));
}
-void NetworkDelegateQt::OnResolveProxy(const GURL&, int, const net::ProxyService&, net::ProxyInfo*)
-{
-}
-
-void NetworkDelegateQt::OnProxyFallback(const net::ProxyServer&, int)
-{
-}
-int NetworkDelegateQt::OnBeforeSendHeaders(net::URLRequest*, const net::CompletionCallback&, net::HttpRequestHeaders*)
+int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionCallback &callback, net::HttpRequestHeaders *headers)
{
return net::OK;
}
-void NetworkDelegateQt::OnBeforeSendProxyHeaders(net::URLRequest*, const net::ProxyInfo&, net::HttpRequestHeaders*)
+void NetworkDelegateQt::OnBeforeSendHeaders(net::URLRequest* request, const net::ProxyInfo& proxy_info,
+ const net::ProxyRetryInfoMap& proxy_retry_info, net::HttpRequestHeaders* headers)
{
}
-void NetworkDelegateQt::OnSendHeaders(net::URLRequest*, const net::HttpRequestHeaders&)
+void NetworkDelegateQt::OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers)
{
}
diff --git a/src/core/network_delegate_qt.h b/src/core/network_delegate_qt.h
index 1324e0da3..4ded56a9d 100644
--- a/src/core/network_delegate_qt.h
+++ b/src/core/network_delegate_qt.h
@@ -76,11 +76,10 @@ public:
virtual int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* newUrl) override;
virtual void OnURLRequestDestroyed(net::URLRequest* request) override;
virtual bool OnCanSetCookie(const net::URLRequest&, const std::string&, net::CookieOptions*) override;
- virtual void OnResolveProxy(const GURL&, int, const net::ProxyService&, net::ProxyInfo*) override;
- virtual void OnProxyFallback(const net::ProxyServer&, int) override;
- virtual int OnBeforeSendHeaders(net::URLRequest*, const net::CompletionCallback&, net::HttpRequestHeaders*) override;
- virtual void OnBeforeSendProxyHeaders(net::URLRequest*, const net::ProxyInfo&, net::HttpRequestHeaders*) override;
- virtual void OnSendHeaders(net::URLRequest*, const net::HttpRequestHeaders&) override;
+ virtual int OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionCallback &callback, net::HttpRequestHeaders *headers) override;
+ virtual void OnBeforeSendHeaders(net::URLRequest* request, const net::ProxyInfo& proxy_info,
+ const net::ProxyRetryInfoMap& proxy_retry_info, net::HttpRequestHeaders* headers) override;
+ virtual void OnStartTransaction(net::URLRequest *request, const net::HttpRequestHeaders &headers) override;
virtual int OnHeadersReceived(net::URLRequest*, const net::CompletionCallback&, const net::HttpResponseHeaders*, scoped_refptr<net::HttpResponseHeaders>*, GURL*) override;
virtual void OnBeforeRedirect(net::URLRequest*, const GURL&) override;
virtual void OnResponseStarted(net::URLRequest*) override;
diff --git a/src/core/ozone_platform_eglfs.cpp b/src/core/ozone_platform_eglfs.cpp
index 6fea4259e..0b560da6c 100644
--- a/src/core/ozone_platform_eglfs.cpp
+++ b/src/core/ozone_platform_eglfs.cpp
@@ -42,7 +42,7 @@
#if defined(USE_OZONE)
#include "base/bind.h"
-#include "media/ozone/media_ozone_platform.h"
+#include "base/memory/ptr_util.h"
#include "ui/events/ozone/device/device_manager.h"
#include "ui/events/ozone/evdev/event_factory_evdev.h"
#include "ui/events/ozone/events_ozone.h"
@@ -57,15 +57,6 @@
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_delegate.h"
-
-namespace media {
-
-MediaOzonePlatform* CreateMediaOzonePlatformEglfs() {
- return new MediaOzonePlatform;
-}
-
-}
-
namespace ui {
namespace {
@@ -157,11 +148,11 @@ GpuPlatformSupportHost* OzonePlatformEglfs::GetGpuPlatformSupportHost() {
return gpu_platform_support_host_.get();
}
-scoped_ptr<PlatformWindow> OzonePlatformEglfs::CreatePlatformWindow(
+std::unique_ptr<PlatformWindow> OzonePlatformEglfs::CreatePlatformWindow(
PlatformWindowDelegate* delegate,
const gfx::Rect& bounds)
{
- return make_scoped_ptr<PlatformWindow>(
+ return base::WrapUnique(
new EglfsWindow(delegate,
event_factory_ozone_.get(),
bounds));
@@ -171,7 +162,7 @@ ui::InputController* OzonePlatformEglfs::GetInputController() {
return input_controller_.get();
}
-scoped_ptr<ui::SystemInputInjector> OzonePlatformEglfs::CreateSystemInputInjector() {
+std::unique_ptr<ui::SystemInputInjector> OzonePlatformEglfs::CreateSystemInputInjector() {
return nullptr; // no input injection support.
}
@@ -179,14 +170,9 @@ ui::OverlayManagerOzone* OzonePlatformEglfs::GetOverlayManager() {
return overlay_manager_.get();
}
-scoped_ptr<ui::NativeDisplayDelegate> OzonePlatformEglfs::CreateNativeDisplayDelegate()
-{
- return scoped_ptr<NativeDisplayDelegate>(new NativeDisplayDelegateOzone());
-}
-
-base::ScopedFD OzonePlatformEglfs::OpenClientNativePixmapDevice() const
+std::unique_ptr<ui::NativeDisplayDelegate> OzonePlatformEglfs::CreateNativeDisplayDelegate()
{
- return base::ScopedFD();
+ return base::WrapUnique(new NativeDisplayDelegateOzone());
}
OzonePlatform* CreateOzonePlatformEglfs() { return new OzonePlatformEglfs; }
diff --git a/src/core/ozone_platform_eglfs.h b/src/core/ozone_platform_eglfs.h
index 3a2dfbcf0..cdc2bd1ce 100644
--- a/src/core/ozone_platform_eglfs.h
+++ b/src/core/ozone_platform_eglfs.h
@@ -61,28 +61,27 @@ class OzonePlatformEglfs : public OzonePlatform {
virtual ui::CursorFactoryOzone* GetCursorFactoryOzone() override;
virtual GpuPlatformSupport* GetGpuPlatformSupport() override;
virtual GpuPlatformSupportHost* GetGpuPlatformSupportHost() override;
- virtual scoped_ptr<PlatformWindow> CreatePlatformWindow(
+ virtual std::unique_ptr<PlatformWindow> CreatePlatformWindow(
PlatformWindowDelegate* delegate,
const gfx::Rect& bounds) override;
- virtual scoped_ptr<ui::NativeDisplayDelegate> CreateNativeDisplayDelegate() override;
- virtual base::ScopedFD OpenClientNativePixmapDevice() const override;
+ virtual std::unique_ptr<ui::NativeDisplayDelegate> CreateNativeDisplayDelegate() override;
virtual ui::InputController* GetInputController() override;
- virtual scoped_ptr<ui::SystemInputInjector> CreateSystemInputInjector() override;
+ virtual std::unique_ptr<ui::SystemInputInjector> CreateSystemInputInjector() override;
virtual ui::OverlayManagerOzone* GetOverlayManager() override;
private:
virtual void InitializeUI() override;
virtual void InitializeGPU() override;
- scoped_ptr<DeviceManager> device_manager_;
+ std::unique_ptr<DeviceManager> device_manager_;
- scoped_ptr<QtWebEngineCore::SurfaceFactoryQt> surface_factory_ozone_;
- scoped_ptr<CursorFactoryOzone> cursor_factory_ozone_;
- scoped_ptr<EventFactoryEvdev> event_factory_ozone_;
+ std::unique_ptr<QtWebEngineCore::SurfaceFactoryQt> surface_factory_ozone_;
+ std::unique_ptr<CursorFactoryOzone> cursor_factory_ozone_;
+ std::unique_ptr<EventFactoryEvdev> event_factory_ozone_;
- scoped_ptr<GpuPlatformSupport> gpu_platform_support_;
- scoped_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
- scoped_ptr<InputController> input_controller_;
- scoped_ptr<OverlayManagerOzone> overlay_manager_;
+ std::unique_ptr<GpuPlatformSupport> gpu_platform_support_;
+ std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
+ std::unique_ptr<InputController> input_controller_;
+ std::unique_ptr<OverlayManagerOzone> overlay_manager_;
DISALLOW_COPY_AND_ASSIGN(OzonePlatformEglfs);
};
diff --git a/src/core/pdfium_printing_wrapper_qt.cpp b/src/core/pdfium_printing_wrapper_qt.cpp
new file mode 100644
index 000000000..165ac743f
--- /dev/null
+++ b/src/core/pdfium_printing_wrapper_qt.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** 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 "pdfium_printing_wrapper_qt.h"
+
+#include <QtCore/qhash.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qpainter.h>
+#include <QtPrintSupport/qprinter.h>
+
+#include "third_party/pdfium/public/fpdf_doc.h"
+#include "third_party/pdfium/public/fpdfview.h"
+
+namespace QtWebEngineCore {
+int PdfiumPrintingWrapperQt::m_libraryUsers = 0;
+
+class PDFiumPageWrapper {
+public:
+ PDFiumPageWrapper(void *data, int pageIndex, int targetWidth, int targetHeight)
+ : m_pageData(FPDF_LoadPage(data, pageIndex))
+ , m_width(FPDF_GetPageWidth(m_pageData))
+ , m_height(FPDF_GetPageHeight(m_pageData))
+ , m_index(pageIndex)
+ , m_image(createImage(targetWidth, targetHeight))
+ {
+ }
+
+ PDFiumPageWrapper()
+ : m_pageData(nullptr)
+ , m_width(-1)
+ , m_height(-1)
+ , m_index(-1)
+ , m_image(QImage())
+ {
+ }
+
+ virtual ~PDFiumPageWrapper()
+ {
+ FPDF_ClosePage(m_pageData);
+ }
+
+ QImage image()
+ {
+ return m_image;
+ }
+
+private:
+ QImage createImage(int targetWidth, int targetHeight)
+ {
+ Q_ASSERT(m_pageData);
+ if (targetWidth <= 0)
+ targetWidth = m_width;
+
+ if (targetHeight <= 0)
+ targetHeight = m_height;
+
+ QImage image(targetWidth, targetHeight, QImage::Format_RGBA8888);
+ Q_ASSERT(!image.isNull());
+ image.fill(0xFFFFFFFF);
+
+ FPDF_BITMAP bitmap = FPDFBitmap_CreateEx(image.width(), image.height(),
+ FPDFBitmap_BGRA,
+ image.scanLine(0), image.bytesPerLine());
+ Q_ASSERT(bitmap);
+
+ FPDF_RenderPageBitmap(bitmap, m_pageData,
+ 0, 0, image.width(), image.height(),
+ 0, 0);
+ FPDFBitmap_Destroy(bitmap);
+ bitmap = nullptr;
+
+ // Map BGRA to RGBA as PDFium currently does not support RGBA bitmaps directly
+ for (int i = 0; i < image.height(); i++) {
+ uchar *pixels = image.scanLine(i);
+ for (int j = 0; j < image.width(); j++) {
+ qSwap(pixels[0], pixels[2]);
+ pixels += 4;
+ }
+ }
+ return image;
+ }
+
+private:
+ void *m_pageData;
+ int m_width;
+ int m_height;
+ int m_index;
+ QImage m_image;
+};
+
+
+PdfiumPrintingWrapperQt::PdfiumPrintingWrapperQt(const void *pdfData, size_t size, const char *password)
+{
+ Q_ASSERT(pdfData);
+ Q_ASSERT(size);
+ if (m_libraryUsers++ == 0)
+ FPDF_InitLibrary();
+
+ m_documentHandle = FPDF_LoadMemDocument(pdfData, static_cast<int>(size), password);
+ m_pageCount = FPDF_GetPageCount(m_documentHandle);
+}
+
+bool PdfiumPrintingWrapperQt::printOnPrinter(QPrinter &printer)
+{
+ if (!m_documentHandle || !m_pageCount) {
+ qWarning("Failure to print on printer %ls: invalid document.\n", qUtf16Printable(printer.printerName()));
+ return false;
+ }
+
+ int toPage = printer.toPage();
+ int fromPage = printer.fromPage();
+ bool ascendingOrder = true;
+
+ if (fromPage == 0 && toPage == 0) {
+ fromPage = 1;
+ toPage = m_pageCount;
+ }
+ fromPage = qMax(1, fromPage);
+ toPage = qMin(m_pageCount, toPage);
+
+ if (printer.pageOrder() == QPrinter::LastPageFirst) {
+ qSwap(fromPage, toPage);
+ ascendingOrder = false;
+ }
+
+ int documentCopies = printer.copyCount();
+ int pageCopies = 1;
+ if (printer.collateCopies()) {
+ pageCopies = documentCopies;
+ documentCopies = 1;
+ }
+
+ QRect printerPageRect = printer.pageRect();
+ int doubledPrinterWidth = 2 * printerPageRect.width();
+ int doubledPrinterHeight = 2 * printerPageRect.height();
+
+ QPainter painter;
+ if (!painter.begin(&printer)) {
+ qWarning("Failure to print on printer %ls: Could not open printer for painting.\n", qUtf16Printable(printer.printerName()));
+ return false;
+ }
+
+ QHash<int, PDFiumPageWrapper*> cachedPages;
+ 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;
+
+ PDFiumPageWrapper *currentPageWrapper;
+ if (!cachedPages.contains(currentPageIndex - 1)) {
+ currentPageWrapper
+ = new PDFiumPageWrapper(m_documentHandle, currentPageIndex - 1
+ , doubledPrinterWidth, doubledPrinterHeight);
+ cachedPages.insert(currentPageIndex - 1, currentPageWrapper);
+ } else {
+ currentPageWrapper = cachedPages.value(currentPageIndex - 1);
+ }
+
+ QImage currentImage = currentPageWrapper->image();
+ painter.drawImage(printerPageRect, 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();
+
+ qDeleteAll(cachedPages);
+
+ return true;
+}
+
+PdfiumPrintingWrapperQt::~PdfiumPrintingWrapperQt()
+{
+ FPDF_CloseDocument(m_documentHandle);
+ if (--m_libraryUsers == 0)
+ FPDF_DestroyLibrary();
+}
+
+}
diff --git a/src/core/pdfium_printing_wrapper_qt.h b/src/core/pdfium_printing_wrapper_qt.h
new file mode 100644
index 000000000..3aaf2b461
--- /dev/null
+++ b/src/core/pdfium_printing_wrapper_qt.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef PDFIUM_PRINTING_WRAPPER_QT_H
+#define PDFIUM_PRINTING_WRAPPER_QT_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+class QPrinter;
+QT_END_NAMESPACE
+
+namespace QtWebEngineCore {
+
+class PdfiumPrintingWrapperQt
+{
+public:
+ PdfiumPrintingWrapperQt(const void *pdfData, size_t size, const char *password = nullptr);
+ virtual ~PdfiumPrintingWrapperQt();
+ bool printOnPrinter(QPrinter &printer);
+ int pageCount() const { return m_pageCount; }
+
+private:
+ static int m_libraryUsers;
+ void *m_documentHandle;
+ int m_pageCount;
+};
+
+} // namespace QtWebEngineCore
+#endif // PDFIUM_PRINTING_WRAPPER_QT_H
diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp
index 9603dc94c..f76f100e6 100644
--- a/src/core/permission_manager_qt.cpp
+++ b/src/core/permission_manager_qt.cpp
@@ -65,6 +65,7 @@ BrowserContextAdapter::PermissionType toQt(content::PermissionType type)
case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
case content::PermissionType::MIDI:
case content::PermissionType::DURABLE_STORAGE:
+ case content::PermissionType::BACKGROUND_SYNC:
case content::PermissionType::NUM:
break;
}
@@ -85,7 +86,7 @@ void PermissionManagerQt::permissionRequestReply(const QUrl &origin, BrowserCont
{
QPair<QUrl, BrowserContextAdapter::PermissionType> key(origin, type);
m_permissions[key] = reply;
- content::PermissionStatus status = reply ? content::PERMISSION_STATUS_GRANTED : content::PERMISSION_STATUS_DENIED;
+ blink::mojom::PermissionStatus status = reply ? blink::mojom::PermissionStatus::GRANTED : blink::mojom::PermissionStatus::DENIED;
auto it = m_requests.begin();
while (it != m_requests.end()) {
if (it->origin == origin && it->type == type) {
@@ -109,14 +110,12 @@ bool PermissionManagerQt::checkPermission(const QUrl &origin, BrowserContextAdap
int PermissionManagerQt::RequestPermission(content::PermissionType permission,
content::RenderFrameHost *frameHost,
const GURL& requesting_origin,
- bool user_gesture,
- const base::Callback<void(content::PermissionStatus)>& callback)
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
{
- Q_UNUSED(user_gesture);
int request_id = ++m_requestIdCount;
BrowserContextAdapter::PermissionType permissionType = toQt(permission);
if (permissionType == BrowserContextAdapter::UnsupportedPermission) {
- callback.Run(content::PERMISSION_STATUS_DENIED);
+ callback.Run(blink::mojom::PermissionStatus::DENIED);
return kNoPendingOperation;
}
// Audio and video-capture should not come this way currently
@@ -140,25 +139,23 @@ int PermissionManagerQt::RequestPermission(content::PermissionType permission,
int PermissionManagerQt::RequestPermissions(const std::vector<content::PermissionType>& permissions,
content::RenderFrameHost* frameHost,
const GURL& requesting_origin,
- bool user_gesture,
- const base::Callback<void(const std::vector<content::PermissionStatus>&)>& callback)
+ const base::Callback<void(const std::vector<blink::mojom::PermissionStatus>&)>& callback)
{
NOTIMPLEMENTED() << "RequestPermissions has not been implemented in QtWebEngine";
- Q_UNUSED(user_gesture);
Q_UNUSED(frameHost);
- std::vector<content::PermissionStatus> result(permissions.size());
+ std::vector<blink::mojom::PermissionStatus> result(permissions.size());
for (content::PermissionType permission : permissions) {
const BrowserContextAdapter::PermissionType permissionType = toQt(permission);
if (permissionType == BrowserContextAdapter::UnsupportedPermission)
- result.push_back(content::PERMISSION_STATUS_DENIED);
+ result.push_back(blink::mojom::PermissionStatus::DENIED);
else {
QPair<QUrl, BrowserContextAdapter::PermissionType> key(toQt(requesting_origin), permissionType);
// TODO: Request permission from UI
if (m_permissions.contains(key) && m_permissions[key])
- result.push_back(content::PERMISSION_STATUS_GRANTED);
+ result.push_back(blink::mojom::PermissionStatus::GRANTED);
else
- result.push_back(content::PERMISSION_STATUS_DENIED);
+ result.push_back(blink::mojom::PermissionStatus::DENIED);
}
}
@@ -172,21 +169,21 @@ void PermissionManagerQt::CancelPermissionRequest(int request_id)
m_requests.remove(request_id);
}
-content::PermissionStatus PermissionManagerQt::GetPermissionStatus(
+blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus(
content::PermissionType permission,
const GURL& requesting_origin,
const GURL& /*embedding_origin*/)
{
const BrowserContextAdapter::PermissionType permissionType = toQt(permission);
if (permissionType == BrowserContextAdapter::UnsupportedPermission)
- return content::PERMISSION_STATUS_DENIED;
+ return blink::mojom::PermissionStatus::DENIED;
QPair<QUrl, BrowserContextAdapter::PermissionType> key(toQt(requesting_origin), permissionType);
if (!m_permissions.contains(key))
- return content::PERMISSION_STATUS_ASK;
+ return blink::mojom::PermissionStatus::ASK;
if (m_permissions[key])
- return content::PERMISSION_STATUS_GRANTED;
- return content::PERMISSION_STATUS_DENIED;
+ return blink::mojom::PermissionStatus::GRANTED;
+ return blink::mojom::PermissionStatus::DENIED;
}
void PermissionManagerQt::ResetPermission(
@@ -214,7 +211,7 @@ int PermissionManagerQt::SubscribePermissionStatusChange(
content::PermissionType permission,
const GURL& requesting_origin,
const GURL& /*embedding_origin*/,
- const base::Callback<void(content::PermissionStatus)>& callback)
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
{
int subscriber_id = ++m_subscriberIdCount;
RequestOrSubscription subscriber = {
diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h
index ff35357d8..e4392b01c 100644
--- a/src/core/permission_manager_qt.h
+++ b/src/core/permission_manager_qt.h
@@ -64,12 +64,11 @@ public:
content::PermissionType permission,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- bool user_gesture,
- const base::Callback<void(content::PermissionStatus)>& callback) override;
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override;
void CancelPermissionRequest(int request_id) override;
- content::PermissionStatus GetPermissionStatus(
+ blink::mojom::PermissionStatus GetPermissionStatus(
content::PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) override;
@@ -83,9 +82,8 @@ public:
const std::vector<content::PermissionType>& permission,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- bool user_gesture,
const base::Callback<void(
- const std::vector<content::PermissionStatus>&)>& callback) override;
+ const std::vector<blink::mojom::PermissionStatus>&)>& callback) override;
void RegisterPermissionUsage(
content::PermissionType permission,
@@ -96,7 +94,7 @@ public:
content::PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin,
- const base::Callback<void(content::PermissionStatus)>& callback) override;
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback) override;
void UnsubscribePermissionStatusChange(int subscription_id) override;
@@ -105,7 +103,7 @@ private:
struct RequestOrSubscription {
PermissionType type;
QUrl origin;
- base::Callback<void(content::PermissionStatus)> callback;
+ base::Callback<void(blink::mojom::PermissionStatus)> callback;
};
QHash<int, RequestOrSubscription> m_requests;
QHash<int, RequestOrSubscription> m_subscribers;
diff --git a/src/core/print_view_manager_base_qt.cpp b/src/core/print_view_manager_base_qt.cpp
index 3e12901b9..8c52e1b18 100644
--- a/src/core/print_view_manager_base_qt.cpp
+++ b/src/core/print_view_manager_base_qt.cpp
@@ -45,7 +45,6 @@
#include "web_engine_context.h"
#include "base/single_thread_task_runner.h"
-#include "base/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -246,7 +245,7 @@ void PrintViewManagerBaseQt::OnDidPrintPage(
#endif
// Only used when |metafile_must_be_valid| is true.
- scoped_ptr<base::SharedMemory> shared_buf;
+ std::unique_ptr<base::SharedMemory> shared_buf;
if (metafile_must_be_valid) {
if (!base::SharedMemory::IsHandleValid(params.metafile_data_handle)) {
NOTREACHED() << "invalid memory handle";
@@ -268,7 +267,7 @@ void PrintViewManagerBaseQt::OnDidPrintPage(
}
}
- scoped_ptr<printing::PdfMetafileSkia> metafile(new printing::PdfMetafileSkia);
+ std::unique_ptr<printing::PdfMetafileSkia> metafile(new printing::PdfMetafileSkia(printing::PDF_SKIA_DOCUMENT_TYPE));
if (metafile_must_be_valid) {
if (!metafile->InitFromData(shared_buf->memory(), params.data_size)) {
NOTREACHED() << "Invalid metafile header";
diff --git a/src/core/print_view_manager_base_qt.h b/src/core/print_view_manager_base_qt.h
index f1e001eee..a8b4b5fc8 100644
--- a/src/core/print_view_manager_base_qt.h
+++ b/src/core/print_view_manager_base_qt.h
@@ -42,8 +42,8 @@
#define PRINT_VIEW_MANAGER_BASE_QT_H
#include "base/memory/ref_counted.h"
-#include "base/prefs/pref_member.h"
#include "base/strings/string16.h"
+#include "components/prefs/pref_member.h"
#include "components/printing/browser/print_manager.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -97,7 +97,7 @@ protected:
int number_pages_; // Number of pages to print in the print job.
int cookie_;
- scoped_ptr<base::DictionaryValue> m_printSettings;
+ std::unique_ptr<base::DictionaryValue> m_printSettings;
// content::NotificationObserver implementation.
void Observe(int,
diff --git a/src/core/print_view_manager_qt.cpp b/src/core/print_view_manager_qt.cpp
index 4cb0e06eb..8f52cc24a 100644
--- a/src/core/print_view_manager_qt.cpp
+++ b/src/core/print_view_manager_qt.cpp
@@ -43,14 +43,17 @@
#include "type_conversion.h"
#include "web_engine_context.h"
-#include <QtGui/QPageLayout>
-#include <QtGui/QPageSize>
+#include <QtGui/qpagelayout.h>
+#include <QtGui/qpagesize.h>
#include "base/values.h"
+#include "base/memory/ref_counted_memory.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/public/browser/browser_thread.h"
+#include "content/public/common/web_preferences.h"
#include "printing/pdf_metafile_skia.h"
#include "printing/print_job_constants.h"
@@ -61,7 +64,7 @@ static const qreal kMicronsToMillimeter = 1000.0f;
static std::vector<char>
GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) {
- scoped_ptr<base::SharedMemory> shared_buf(
+ std::unique_ptr<base::SharedMemory> shared_buf(
new base::SharedMemory(handle, true));
if (!shared_buf->Map(data_size)) {
@@ -74,7 +77,7 @@ GetStdVectorFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) {
static scoped_refptr<base::RefCountedBytes>
GetBytesFromHandle(base::SharedMemoryHandle handle, uint32_t data_size) {
- scoped_ptr<base::SharedMemory> shared_buf(
+ std::unique_ptr<base::SharedMemory> shared_buf(
new base::SharedMemory(handle, true));
if (!shared_buf->Map(data_size)) {
@@ -92,7 +95,7 @@ static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data,
DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
DCHECK_GT(data->size(), 0U);
- printing::PdfMetafileSkia metafile;
+ printing::PdfMetafileSkia metafile(printing::PDF_SKIA_DOCUMENT_TYPE);
metafile.InitFromData(static_cast<const void*>(data->front()), data->size());
base::File file(path,
@@ -101,43 +104,58 @@ static void SavePdfFile(scoped_refptr<base::RefCountedBytes> data,
metafile.SaveTo(&file);
}
-static void applyQPageLayoutSettingsToDictionary(const QPageLayout& pageLayout, base::DictionaryValue& print_settings)
+static base::DictionaryValue *createPrintSettings()
{
+ base::DictionaryValue *printSettings = new base::DictionaryValue();
// TO DO: Check if we can use the request ID from Qt here somehow.
static int internalRequestId = 0;
- print_settings.SetBoolean(printing::kIsFirstRequest, internalRequestId++ == 0);
- print_settings.SetInteger(printing::kPreviewRequestID, internalRequestId);
+ printSettings->SetBoolean(printing::kIsFirstRequest, internalRequestId++ == 0);
+ printSettings->SetInteger(printing::kPreviewRequestID, internalRequestId);
+
+ // The following are standard settings that Chromium expects to be set.
+ printSettings->SetBoolean(printing::kSettingPrintToPDF, true);
+ printSettings->SetBoolean(printing::kSettingCloudPrintDialog, false);
+ printSettings->SetBoolean(printing::kSettingPrintWithPrivet, false);
+ printSettings->SetBoolean(printing::kSettingPrintWithExtension, false);
+
+ printSettings->SetBoolean(printing::kSettingGenerateDraftData, false);
+ printSettings->SetBoolean(printing::kSettingPreviewModifiable, false);
+ printSettings->SetInteger(printing::kSettingDuplexMode, printing::SIMPLEX);
+ printSettings->SetInteger(printing::kSettingCopies, 1);
+ printSettings->SetBoolean(printing::kSettingCollate, false);
+ printSettings->SetBoolean(printing::kSettingGenerateDraftData, false);
+ printSettings->SetBoolean(printing::kSettingPreviewModifiable, false);
+
+ printSettings->SetBoolean(printing::kSettingShouldPrintSelectionOnly, false);
+ printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds, true);
+ printSettings->SetBoolean(printing::kSettingHeaderFooterEnabled, false);
+ printSettings->SetString(printing::kSettingDeviceName, "");
+ printSettings->SetInteger(printing::kPreviewUIID, 12345678);
+
+ return printSettings;
+}
+
+static void applyQPageLayoutSettingsToDictionary(const QPageLayout &pageLayout, base::DictionaryValue &printSettings)
+{
//Set page size attributes, chromium expects these in micrometers
QSizeF pageSizeInMilimeter = pageLayout.pageSize().size(QPageSize::Millimeter);
- scoped_ptr<base::DictionaryValue> sizeDict(new base::DictionaryValue);
+ std::unique_ptr<base::DictionaryValue> sizeDict(new base::DictionaryValue);
sizeDict->SetInteger(printing::kSettingMediaSizeWidthMicrons, pageSizeInMilimeter.width() * kMicronsToMillimeter);
sizeDict->SetInteger(printing::kSettingMediaSizeHeightMicrons, pageSizeInMilimeter.height() * kMicronsToMillimeter);
- print_settings.Set(printing::kSettingMediaSize, std::move(sizeDict));
-
- print_settings.SetBoolean(printing::kSettingLandscape, pageLayout.orientation() == QPageLayout::Landscape);
-
- // The following are standard settings that Chromium expects to be set.
- print_settings.SetBoolean(printing::kSettingPrintToPDF, true);
- print_settings.SetBoolean(printing::kSettingCloudPrintDialog, false);
- print_settings.SetBoolean(printing::kSettingPrintWithPrivet, false);
- print_settings.SetBoolean(printing::kSettingPrintWithExtension, false);
-
- print_settings.SetBoolean(printing::kSettingGenerateDraftData, false);
- print_settings.SetBoolean(printing::kSettingPreviewModifiable, false);
- print_settings.SetInteger(printing::kSettingColor, printing::COLOR);
- print_settings.SetInteger(printing::kSettingDuplexMode, printing::SIMPLEX);
- print_settings.SetInteger(printing::kSettingDuplexMode, printing::UNKNOWN_DUPLEX_MODE);
- print_settings.SetInteger(printing::kSettingCopies, 1);
- print_settings.SetBoolean(printing::kSettingCollate, false);
- print_settings.SetBoolean(printing::kSettingGenerateDraftData, false);
- print_settings.SetBoolean(printing::kSettingPreviewModifiable, false);
-
- print_settings.SetBoolean(printing::kSettingShouldPrintSelectionOnly, false);
- print_settings.SetBoolean(printing::kSettingShouldPrintBackgrounds, false);
- print_settings.SetBoolean(printing::kSettingHeaderFooterEnabled, false);
- print_settings.SetString(printing::kSettingDeviceName, "");
- print_settings.SetInteger(printing::kPreviewUIID, 12345678);
+ printSettings.Set(printing::kSettingMediaSize, std::move(sizeDict));
+
+ // Apply page margins
+ QMargins pageMarginsInPoints = pageLayout.marginsPoints();
+ std::unique_ptr<base::DictionaryValue> marginsDict(new base::DictionaryValue);
+ marginsDict->SetInteger(printing::kSettingMarginTop, pageMarginsInPoints.top());
+ marginsDict->SetInteger(printing::kSettingMarginBottom, pageMarginsInPoints.bottom());
+ marginsDict->SetInteger(printing::kSettingMarginLeft, pageMarginsInPoints.left());
+ marginsDict->SetInteger(printing::kSettingMarginRight, pageMarginsInPoints.right());
+ printSettings.Set(printing::kSettingMarginsCustom, std::move(marginsDict));
+ printSettings.SetInteger(printing::kSettingMarginsType, printing::CUSTOM_MARGINS);
+
+ printSettings.SetBoolean(printing::kSettingLandscape, pageLayout.orientation() == QPageLayout::Landscape);
}
} // namespace
@@ -149,20 +167,20 @@ PrintViewManagerQt::~PrintViewManagerQt()
}
#if defined(ENABLE_BASIC_PRINTING)
-bool PrintViewManagerQt::PrintToPDF(const QPageLayout &pageLayout, const QString &filePath)
+bool PrintViewManagerQt::PrintToPDF(const QPageLayout &pageLayout, bool printInColor, const QString &filePath)
{
if (m_printSettings || !filePath.length())
return false;
m_pdfOutputPath = toFilePath(filePath);
- if (!PrintToPDFInternal(pageLayout)) {
+ if (!PrintToPDFInternal(pageLayout, printInColor)) {
resetPdfState();
return false;
}
return true;
}
-bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, const PrintToPDFCallback& callback)
+bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, bool printInColor, const PrintToPDFCallback& callback)
{
if (callback.is_null())
return false;
@@ -176,7 +194,7 @@ bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, c
}
m_pdfPrintCallback = callback;
- if (!PrintToPDFInternal(pageLayout)) {
+ if (!PrintToPDFInternal(pageLayout, printInColor)) {
content::BrowserThread::PostTask(content::BrowserThread::UI,
FROM_HERE,
base::Bind(callback, std::vector<char>()));
@@ -187,12 +205,16 @@ bool PrintViewManagerQt::PrintToPDFWithCallback(const QPageLayout &pageLayout, c
return true;
}
-bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout)
+bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, bool printInColor)
{
if (!pageLayout.isValid())
return false;
- m_printSettings.reset(new base::DictionaryValue());
+ m_printSettings.reset(createPrintSettings());
+
+ m_printSettings->SetInteger(printing::kSettingColor, printInColor ? printing::COLOR : printing::GRAYSCALE);
applyQPageLayoutSettingsToDictionary(pageLayout, *m_printSettings);
+ m_printSettings->SetBoolean(printing::kSettingShouldPrintBackgrounds
+ , web_contents()->GetRenderViewHost()->GetWebkitPreferences().should_print_backgrounds);
return Send(new PrintMsg_InitiatePrintPreview(routing_id(), false));
}
diff --git a/src/core/print_view_manager_qt.h b/src/core/print_view_manager_qt.h
index 88a499f1b..668516096 100644
--- a/src/core/print_view_manager_qt.h
+++ b/src/core/print_view_manager_qt.h
@@ -45,8 +45,8 @@
#include <QtWebEngineCore/qtwebenginecoreglobal.h>
#include "base/memory/ref_counted.h"
-#include "base/prefs/pref_member.h"
#include "base/strings/string16.h"
+#include "components/prefs/pref_member.h"
#include "components/printing/browser/print_manager.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -83,8 +83,8 @@ public:
typedef base::Callback<void(const std::vector<char> &result)> PrintToPDFCallback;
#if defined(ENABLE_BASIC_PRINTING)
// Method to print a page to a Pdf document with page size \a pageSize in location \a filePath.
- bool PrintToPDF(const QPageLayout& pageLayout, const QString& filePath);
- bool PrintToPDFWithCallback(const QPageLayout& pageLayout, const PrintToPDFCallback& callback);
+ bool PrintToPDF(const QPageLayout &pageLayout, bool printInColor, const QString &filePath);
+ bool PrintToPDFWithCallback(const QPageLayout &pageLayout, bool printInColor, const PrintToPDFCallback &callback);
#endif // ENABLE_BASIC_PRINTING
// PrintedPagesSource implementation.
@@ -109,7 +109,7 @@ protected:
void OnMetafileReadyForPrinting(const PrintHostMsg_DidPreviewDocument_Params& params);
#if defined(ENABLE_BASIC_PRINTING)
- bool PrintToPDFInternal(const QPageLayout &);
+ bool PrintToPDFInternal(const QPageLayout &, bool printInColor);
#endif //
base::FilePath m_pdfOutputPath;
diff --git a/src/core/printing_message_filter_qt.cpp b/src/core/printing_message_filter_qt.cpp
index ba4d5c6e6..a84ec491f 100644
--- a/src/core/printing_message_filter_qt.cpp
+++ b/src/core/printing_message_filter_qt.cpp
@@ -76,9 +76,6 @@ void PrintingMessageFilterQt::OverrideThreadForMessage(
bool PrintingMessageFilterQt::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PrintingMessageFilterQt, message)
-#if defined(OS_WIN)
- IPC_MESSAGE_HANDLER(PrintHostMsg_DuplicateSection, OnDuplicateSection)
-#endif
IPC_MESSAGE_HANDLER(PrintHostMsg_IsPrintingEnabled, OnIsPrintingEnabled)
IPC_MESSAGE_HANDLER_DELAY_REPLY(PrintHostMsg_GetDefaultPrintSettings,
OnGetDefaultPrintSettings)
@@ -91,17 +88,6 @@ bool PrintingMessageFilterQt::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-#if defined(OS_WIN)
-void PrintingMessageFilterQt::OnDuplicateSection(
- base::SharedMemoryHandle renderer_handle,
- base::SharedMemoryHandle* browser_handle) {
- // Duplicate the handle in this process right now so the memory is kept alive
- // (even if it is not mapped)
- base::SharedMemory shared_buf(renderer_handle, true, PeerHandle());
- shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), browser_handle);
-}
-#endif
-
void PrintingMessageFilterQt::OnIsPrintingEnabled(bool* is_enabled) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
*is_enabled = true;
@@ -201,7 +187,7 @@ void PrintingMessageFilterQt::OnScriptedPrintReply(
void PrintingMessageFilterQt::OnUpdatePrintSettings(
int document_cookie, const base::DictionaryValue& job_settings,
IPC::Message* reply_msg) {
- scoped_ptr<base::DictionaryValue> new_settings(job_settings.DeepCopy());
+ std::unique_ptr<base::DictionaryValue> new_settings(job_settings.DeepCopy());
scoped_refptr<printing::PrinterQuery> printer_query;
printer_query = queue_->PopPrinterQuery(document_cookie);
diff --git a/src/core/printing_message_filter_qt.h b/src/core/printing_message_filter_qt.h
index 95d63f570..156a31250 100644
--- a/src/core/printing_message_filter_qt.h
+++ b/src/core/printing_message_filter_qt.h
@@ -44,7 +44,7 @@
#include <string>
#include "base/compiler_specific.h"
-#include "base/prefs/pref_member.h"
+#include "components/prefs/pref_member.h"
#include "content/public/browser/browser_message_filter.h"
#if defined(OS_WIN)
@@ -84,12 +84,6 @@ class PrintingMessageFilterQt : public content::BrowserMessageFilter {
private:
~PrintingMessageFilterQt() override;
-#if defined(OS_WIN)
- // Used to pass resulting EMF from renderer to browser in printing.
- void OnDuplicateSection(base::SharedMemoryHandle renderer_handle,
- base::SharedMemoryHandle* browser_handle);
-#endif
-
// GetPrintSettingsForRenderView must be called via PostTask and
// base::Bind. Collapse the settings-specific params into a
// struct to avoid running into issues with too many params
diff --git a/src/core/proxy_config_service_qt.cpp b/src/core/proxy_config_service_qt.cpp
index bd5d0375d..28a36d37f 100644
--- a/src/core/proxy_config_service_qt.cpp
+++ b/src/core/proxy_config_service_qt.cpp
@@ -69,7 +69,7 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt
//================ Based on ChromeProxyConfigService =======================
-ProxyConfigServiceQt::ProxyConfigServiceQt(scoped_ptr<ProxyConfigService> baseService)
+ProxyConfigServiceQt::ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService)
: m_baseService(baseService.release()),
m_registeredObserver(false)
{
diff --git a/src/core/proxy_config_service_qt.h b/src/core/proxy_config_service_qt.h
index da24e3337..f2f9a2210 100644
--- a/src/core/proxy_config_service_qt.h
+++ b/src/core/proxy_config_service_qt.h
@@ -41,7 +41,6 @@
#define PROXY_CONFIG_SERVICE_QT_H
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "net/proxy/proxy_config.h"
@@ -56,7 +55,7 @@ public:
static net::ProxyServer fromQNetworkProxy(const QNetworkProxy &);
- explicit ProxyConfigServiceQt(scoped_ptr<ProxyConfigService> baseService);
+ explicit ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService);
~ProxyConfigServiceQt() override;
// ProxyConfigService implementation:
@@ -73,7 +72,7 @@ private:
// Makes sure that the observer registration with the base service is set up.
void RegisterObserver();
- scoped_ptr<net::ProxyConfigService> m_baseService;
+ std::unique_ptr<net::ProxyConfigService> m_baseService;
base::ObserverList<net::ProxyConfigService::Observer, true> m_observers;
// Keep the last QNetworkProxy::applicationProxy state around.
diff --git a/src/core/qtwebengine.gypi b/src/core/qtwebengine.gypi
index 816962d3d..d0ab01534 100644
--- a/src/core/qtwebengine.gypi
+++ b/src/core/qtwebengine.gypi
@@ -8,15 +8,18 @@
'dependencies': [
'<(chromium_src_dir)/base/base.gyp:base',
'<(chromium_src_dir)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- '<(chromium_src_dir)/chrome/tools/convert_dict/convert_dict.gyp:convert_dict_lib',
+ '<(chromium_src_dir)/components/components.gyp:cdm_renderer',
'<(chromium_src_dir)/components/components.gyp:devtools_discovery',
'<(chromium_src_dir)/components/components.gyp:devtools_http_handler',
'<(chromium_src_dir)/components/components.gyp:error_page_renderer',
+ '<(chromium_src_dir)/components/components.gyp:keyed_service_content',
+ '<(chromium_src_dir)/components/components.gyp:keyed_service_core',
+ '<(chromium_src_dir)/components/components.gyp:pref_registry',
+ '<(chromium_src_dir)/components/components.gyp:user_prefs',
'<(chromium_src_dir)/components/components.gyp:visitedlink_browser',
'<(chromium_src_dir)/components/components.gyp:visitedlink_renderer',
'<(chromium_src_dir)/components/components.gyp:web_cache_browser',
'<(chromium_src_dir)/components/components.gyp:web_cache_renderer',
- '<(chromium_src_dir)/components/components.gyp:cdm_renderer',
'<(chromium_src_dir)/content/content.gyp:content',
'<(chromium_src_dir)/content/content.gyp:content_app_browser',
'<(chromium_src_dir)/content/content.gyp:content_browser',
@@ -36,7 +39,7 @@
'<(chromium_src_dir)/ui/base/ui_base.gyp:ui_base',
'<(chromium_src_dir)/ui/gl/gl.gyp:gl',
'<(chromium_src_dir)/url/url.gyp:url_lib',
- '<(chromium_src_dir)/v8/tools/gyp/v8.gyp:v8',
+ '<(chromium_src_dir)/v8/src/v8.gyp:v8',
'<(qtwebengine_root)/src/core/chrome_qt.gyp:chrome_qt',
],
@@ -85,7 +88,8 @@
},
},
'dependencies': [
- '<(chromium_src_dir)/ui/events/ozone/events_ozone.gyp:events_ozone_evdev'
+ '<(chromium_src_dir)/ui/events/ozone/events_ozone.gyp:events_ozone_evdev',
+ '<(chromium_src_dir)/ui/ozone/ozone.gyp:ozone_common',
]
}],
['qt_os=="win32" and qt_gl=="opengl"', {
diff --git a/src/core/qtwebengine_extras.gypi b/src/core/qtwebengine_extras.gypi
index 229421efa..8e4c655a9 100644
--- a/src/core/qtwebengine_extras.gypi
+++ b/src/core/qtwebengine_extras.gypi
@@ -32,21 +32,28 @@
['exclude', 'browser/renderer_host/render_widget_host_view_mac\\.(mm|h)$'],
['exclude', 'browser/renderer_host/render_widget_host_view_win\\.(cc|h)$'],
['exclude', 'common/font_list_pango\\.cc$'],
- ['exclude', 'browser/accessibility/browser_accessibility_cocoa\\.(cc|h)$'],
+ ['exclude', 'browser/accessibility/browser_accessibility_cocoa\\.(mm|h)$'],
['exclude', 'browser/accessibility/browser_accessibility_gtk\\.(cc|h)$'],
- ['exclude', 'browser/accessibility/browser_accessibility_mac\\.(cc|h)$'],
+ ['exclude', 'browser/accessibility/browser_accessibility_mac\\.(mm|h)$'],
['exclude', 'browser/accessibility/browser_accessibility_win\\.(cc|h)$'],
+ ['exclude', 'browser/accessibility/browser_accessibility_event_win\\.(cc|h)$'],
['exclude', 'browser/accessibility/browser_accessibility_manager_gtk\\.(cc|h)$'],
- ['exclude', 'browser/accessibility/browser_accessibility_manager_mac\\.(cc|h)$'],
+ ['exclude', 'browser/accessibility/browser_accessibility_manager_mac\\.(mm|h)$'],
['exclude', 'browser/accessibility/browser_accessibility_manager_win\\.(cc|h)$'],
['exclude', 'command_buffer/service/async_pixel_transfer_manager_egl\\.(cc|h)$'],
['exclude', 'common/gpu/image_transport_surface_linux\\.cc$'],
['exclude', 'common/gpu/image_transport_surface_win\\.cc$'],
['exclude', 'gl_surface_egl\\.cc$'],
+ ['exclude', 'gl_surface_egl_ozone\\.cc$'],
+ ['exclude', 'gl_surface_egl_win\\.cc$'],
+ ['exclude', 'gl_surface_egl_x11\\.cc$'],
['exclude', 'gl_surface_glx\\.cc$'],
- ['exclude', 'gl_surface_x11\\.cc$'],
- ['exclude', 'gl_surface_win\\.cc$'],
['exclude', 'gl_surface_ozone\\.cc$'],
+ ['exclude', 'gl_factory_ozone\\.cc$'],
+ ['exclude', 'gl_factory_win\\.cc$'],
+ ['exclude', 'gl_initializer_ozone\\.cc$'],
+ ['exclude', 'gl_initializer_win\\.cc$'],
+ ['exclude', 'gl_initializer_x11\\.cc$'],
# Avoid the ATL dependency to allow building with VS Express
['exclude', 'browser/accessibility/accessibility_tree_formatter\\.(cc|h)$',],
['exclude', 'browser/accessibility/accessibility_tree_formatter_mac\\.(mm|h)$',],
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index f45db6bf4..77fd55aab 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -343,18 +343,14 @@ gfx::NativeView RenderWidgetHostViewQt::GetNativeView() const
return gfx::NativeView();
}
-gfx::NativeViewId RenderWidgetHostViewQt::GetNativeViewId() const
-{
- return 0;
-}
-
gfx::NativeViewAccessible RenderWidgetHostViewQt::GetNativeViewAccessible()
{
return 0;
}
-content::BrowserAccessibilityManager* RenderWidgetHostViewQt::CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate)
+content::BrowserAccessibilityManager* RenderWidgetHostViewQt::CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate, bool for_root_frame)
{
+ Q_UNUSED(for_root_frame); // FIXME
#ifndef QT_NO_ACCESSIBILITY
return new content::BrowserAccessibilityManagerQt(
m_adapterClient->accessibilityParentObject(),
@@ -435,11 +431,6 @@ void RenderWidgetHostViewQt::UnlockMouse()
m_host->LostMouseLock();
}
-void RenderWidgetHostViewQt::MovePluginWindows(const std::vector<content::WebPluginGeometry>&)
-{
- // QT_NOT_YET_IMPLEMENTED
-}
-
void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor)
{
content::WebCursor::CursorInfo cursorInfo;
@@ -580,7 +571,7 @@ void RenderWidgetHostViewQt::SetIsLoading(bool)
// We use WebContentsDelegateQt::LoadingStateChanged to notify about loading state.
}
-void RenderWidgetHostViewQt::TextInputStateChanged(const ViewHostMsg_TextInputState_Params &params)
+void RenderWidgetHostViewQt::TextInputStateChanged(const content::TextInputState &params)
{
m_currentInputType = params.type;
m_delegate->inputMethodStateChanged(params.type != ui::TEXT_INPUT_TYPE_NONE);
@@ -612,7 +603,7 @@ void RenderWidgetHostViewQt::Destroy()
void RenderWidgetHostViewQt::SetTooltipText(const base::string16 &tooltip_text)
{
- m_delegate->setTooltip(toQt(tooltip_text));
+ m_adapterClient->setToolTip(toQt(tooltip_text));
}
void RenderWidgetHostViewQt::SelectionBoundsChanged(const ViewHostMsg_SelectionBounds_Params &params)
@@ -664,19 +655,19 @@ void RenderWidgetHostViewQt::UnlockCompositingSurface()
{
}
-void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, scoped_ptr<cc::CompositorFrame> frame)
+void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, cc::CompositorFrame frame)
{
- bool scrollOffsetChanged = (m_lastScrollOffset != frame->metadata.root_scroll_offset);
- bool contentsSizeChanged = (m_lastContentsSize != frame->metadata.root_layer_size);
- m_lastScrollOffset = frame->metadata.root_scroll_offset;
- m_lastContentsSize = frame->metadata.root_layer_size;
+ bool scrollOffsetChanged = (m_lastScrollOffset != frame.metadata.root_scroll_offset);
+ bool contentsSizeChanged = (m_lastContentsSize != frame.metadata.root_layer_size);
+ m_lastScrollOffset = frame.metadata.root_scroll_offset;
+ m_lastContentsSize = frame.metadata.root_layer_size;
Q_ASSERT(!m_needsDelegatedFrameAck);
m_needsDelegatedFrameAck = true;
m_pendingOutputSurfaceId = output_surface_id;
- Q_ASSERT(frame->delegated_frame_data);
+ Q_ASSERT(frame.delegated_frame_data);
Q_ASSERT(!m_chromiumCompositorData->frameData || m_chromiumCompositorData->frameData->resource_list.empty());
- m_chromiumCompositorData->frameData = std::move(frame->delegated_frame_data);
- m_chromiumCompositorData->frameDevicePixelRatio = frame->metadata.device_scale_factor;
+ m_chromiumCompositorData->frameData = std::move(frame.delegated_frame_data);
+ m_chromiumCompositorData->frameDevicePixelRatio = frame.metadata.device_scale_factor;
// Support experimental.viewport.devicePixelRatio, see GetScreenInfo implementation below.
float dpiScale = this->dpiScale();
@@ -720,11 +711,6 @@ void RenderWidgetHostViewQt::ClearCompositorFrame()
{
}
-bool RenderWidgetHostViewQt::GetScreenColorProfile(std::vector<char>*)
-{
- return false;
-}
-
void RenderWidgetHostViewQt::SelectionChanged(const base::string16 &text, size_t offset, const gfx::Range &range)
{
content::RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
@@ -882,7 +868,7 @@ void RenderWidgetHostViewQt::processMotionEvent(const ui::MotionEvent &motionEve
return;
blink::WebTouchEvent touchEvent = ui::CreateWebTouchEventFromMotionEvent(motionEvent,
- result.did_generate_scroll);
+ result.moved_beyond_slop_region);
m_host->ForwardTouchEventWithLatencyInfo(touchEvent, CreateLatencyInfo(touchEvent));
}
@@ -1032,14 +1018,6 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
}
};
- auto setCompositionForPreEditString = [&](){
- ensureValidSelectionRange();
- m_host->ImeSetComposition(toString16(preeditString),
- underlines,
- selectionRange.start(),
- selectionRange.end());
- };
-
Q_FOREACH (const QInputMethodEvent::Attribute &attribute, attributes) {
switch (attribute.type) {
case QInputMethodEvent::TextFormat: {
@@ -1067,9 +1045,19 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
}
}
+ gfx::Range replacementRange = (replacementLength > 0) ? gfx::Range(replacementStart, replacementStart + replacementLength)
+ : gfx::Range::InvalidRange();
+
+ auto setCompositionForPreEditString = [&](){
+ ensureValidSelectionRange();
+ m_host->ImeSetComposition(toString16(preeditString),
+ underlines,
+ replacementRange,
+ selectionRange.start(),
+ selectionRange.end());
+ };
+
if (!commitString.isEmpty()) {
- gfx::Range replacementRange = (replacementLength > 0) ? gfx::Range(replacementStart, replacementStart + replacementLength)
- : gfx::Range::InvalidRange();
m_host->ImeConfirmComposition(toString16(commitString), replacementRange, false);
// We might get a commit string and a pre-edit string in a single event, which means
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index 523d1c49d..d6c77fada 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -42,13 +42,12 @@
#include "render_widget_host_view_qt_delegate.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "cc/resources/transferable_resource.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/common/gpu/gpu_messages.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>
@@ -120,7 +119,6 @@ public:
virtual gfx::Vector2dF GetLastScrollOffset() const Q_DECL_OVERRIDE;
virtual gfx::Size GetPhysicalBackingSize() const Q_DECL_OVERRIDE;
virtual gfx::NativeView GetNativeView() const Q_DECL_OVERRIDE;
- virtual gfx::NativeViewId GetNativeViewId() const Q_DECL_OVERRIDE;
virtual gfx::NativeViewAccessible GetNativeViewAccessible() Q_DECL_OVERRIDE;
virtual void Focus() Q_DECL_OVERRIDE;
virtual bool HasFocus() const Q_DECL_OVERRIDE;
@@ -132,10 +130,9 @@ public:
virtual void SetBackgroundColor(SkColor color) Q_DECL_OVERRIDE;
virtual bool LockMouse() Q_DECL_OVERRIDE;
virtual void UnlockMouse() Q_DECL_OVERRIDE;
- virtual void MovePluginWindows(const std::vector<content::WebPluginGeometry>&) Q_DECL_OVERRIDE;
virtual void UpdateCursor(const content::WebCursor&) Q_DECL_OVERRIDE;
virtual void SetIsLoading(bool) Q_DECL_OVERRIDE;
- virtual void TextInputStateChanged(const ViewHostMsg_TextInputState_Params&) Q_DECL_OVERRIDE;
+ virtual void TextInputStateChanged(const content::TextInputState& params) Q_DECL_OVERRIDE;
virtual void ImeCancelComposition() Q_DECL_OVERRIDE;
virtual void ImeCompositionRangeChanged(const gfx::Range&, const std::vector<gfx::Rect>&) Q_DECL_OVERRIDE;
virtual void RenderProcessGone(base::TerminationStatus, int) Q_DECL_OVERRIDE;
@@ -147,12 +144,12 @@ public:
virtual bool CanCopyToVideoFrame() const Q_DECL_OVERRIDE;
virtual bool HasAcceleratedSurface(const gfx::Size&) Q_DECL_OVERRIDE;
- virtual void OnSwapCompositorFrame(uint32_t output_surface_id, scoped_ptr<cc::CompositorFrame> frame) Q_DECL_OVERRIDE;
+ virtual void OnSwapCompositorFrame(uint32_t output_surface_id, cc::CompositorFrame frame) Q_DECL_OVERRIDE;
+
virtual void GetScreenInfo(blink::WebScreenInfo* results) Q_DECL_OVERRIDE;
virtual gfx::Rect GetBoundsInRootWindow() Q_DECL_OVERRIDE;
virtual void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, content::InputEventAckState ack_result) Q_DECL_OVERRIDE;
virtual void ClearCompositorFrame() Q_DECL_OVERRIDE;
- virtual bool GetScreenColorProfile(std::vector<char>*) Q_DECL_OVERRIDE;
virtual void LockCompositingSurface() Q_DECL_OVERRIDE;
virtual void UnlockCompositingSurface() Q_DECL_OVERRIDE;
@@ -184,26 +181,15 @@ public:
virtual void SetActive(bool active) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
virtual bool IsSpeaking() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return false; }
virtual void SpeakSelection() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
- virtual bool PostProcessEventForPluginIme(const content::NativeWebKeyboardEvent& event) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return false; }
virtual void StopSpeaking() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
- virtual void SetWindowVisibility(bool visible) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
virtual bool SupportsSpeech() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return false; }
virtual void ShowDefinitionForSelection() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
- virtual void WindowFrameChanged() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
+ virtual ui::AcceleratedWidgetMac *GetAcceleratedWidgetMac() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED; return nullptr; }
#endif // defined(OS_MACOSX)
-#if defined(OS_WIN)
-#if defined(USE_AURA)
- virtual void SetParentNativeViewAccessible(gfx::NativeViewAccessible accessible_parent) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
- virtual gfx::NativeViewId GetParentForWindowlessPlugin() const Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED return gfx::NativeViewId(); }
-#else
- virtual void SetClickthroughRegion(SkRegion *) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
- virtual void WillWmDestroy(void) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
-#endif // defined(USE_AURA)
-#endif // defined(OS_WIN)
// Overridden from content::BrowserAccessibilityDelegate
- virtual content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate) Q_DECL_OVERRIDE;
+ virtual content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate, bool for_root_frame) Q_DECL_OVERRIDE;
#ifndef QT_NO_ACCESSIBILITY
virtual void accessibilityActiveChanged(bool active) Q_DECL_OVERRIDE;
#endif // QT_NO_ACCESSIBILITY
@@ -227,7 +213,7 @@ private:
bool m_touchMotionStarted;
QMap<int, int> m_touchIdMapping;
QList<QTouchEvent::TouchPoint> m_previousTouchPoints;
- scoped_ptr<RenderWidgetHostViewQtDelegate> m_delegate;
+ std::unique_ptr<RenderWidgetHostViewQtDelegate> m_delegate;
QExplicitlySharedDataPointer<ChromiumCompositorData> m_chromiumCompositorData;
cc::ReturnedResourceArray m_resourcesToRelease;
diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h
index ce6ec730a..1e50c8f08 100644
--- a/src/core/render_widget_host_view_qt_delegate.h
+++ b/src/core/render_widget_host_view_qt_delegate.h
@@ -49,13 +49,25 @@ QT_BEGIN_NAMESPACE
class QCursor;
class QEvent;
class QPainter;
-class QSGImageNode;
class QSGLayer;
class QSGNode;
+class QSGRectangleNode;
class QSGTexture;
class QVariant;
class QWindow;
class QInputMethodEvent;
+
+#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0))
+class QSGImageNode;
+typedef QSGImageNode QSGInternalImageNode;
+class QSGSimpleTextureNode;
+typedef QSGSimpleTextureNode QSGTextureNode;
+#else
+class QSGInternalImageNode;
+class QSGImageNode;
+typedef QSGImageNode QSGTextureNode;
+#endif
+
QT_END_NAMESPACE
namespace QtWebEngineCore {
@@ -92,13 +104,14 @@ public:
virtual QWindow* window() const = 0;
virtual QSGTexture *createTextureFromImage(const QImage &) = 0;
virtual QSGLayer *createLayer() = 0;
- virtual QSGImageNode *createImageNode() = 0;
+ virtual QSGInternalImageNode *createImageNode() = 0;
+ virtual QSGTextureNode *createTextureNode() = 0;
+ virtual QSGRectangleNode *createRectangleNode() = 0;
virtual void update() = 0;
virtual void updateCursor(const QCursor &) = 0;
virtual void resize(int width, int height) = 0;
virtual void move(const QPoint &) = 0;
virtual void inputMethodStateChanged(bool editorVisible) = 0;
- virtual void setTooltip(const QString &) = 0;
virtual void setClearColor(const QColor &color) = 0;
};
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
index 5d1780cbe..a6e35f4be 100644
--- a/src/core/renderer/content_renderer_client_qt.cpp
+++ b/src/core/renderer/content_renderer_client_qt.cpp
@@ -43,18 +43,18 @@
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/localized_error.h"
#if defined(ENABLE_SPELLCHECK)
#include "chrome/renderer/spellchecker/spellcheck.h"
#include "chrome/renderer/spellchecker/spellcheck_provider.h"
#endif
-#include "components/cdm/renderer/widevine_key_systems.h"
+#include "components/cdm/renderer/widevine_key_system_properties.h"
#include "components/error_page/common/error_page_params.h"
+#include "components/error_page/common/localized_error.h"
#if defined (ENABLE_BASIC_PRINTING)
#include "components/printing/renderer/print_web_view_helper.h"
#endif // if defined(ENABLE_BASIC_PRINTING)
#include "components/visitedlink/renderer/visitedlink_slave.h"
-#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+#include "components/web_cache/renderer/web_cache_impl.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
@@ -76,7 +76,7 @@
#include "renderer/render_view_observer_qt.h"
#include "renderer/user_resource_controller.h"
-#include "grit/renderer_resources.h"
+#include "components/grit/components_resources.h"
#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
@@ -85,17 +85,6 @@ namespace QtWebEngineCore {
static const char kHttpErrorDomain[] = "http";
static const char kQrcSchemeQt[] = "qrc";
-class RenderProcessObserverQt : public content::RenderProcessObserver {
-public:
- void WebKitInitialized() override
- {
- // Can only be done after blink is initialized.
- blink::WebString qrcScheme(base::ASCIIToUTF16(kQrcSchemeQt));
- // mark qrc as a secure scheme (avoids deprecation warnings)
- blink::WebSecurityPolicy::registerURLSchemeAsSecure(qrcScheme);
- }
-};
-
ContentRendererClientQt::ContentRendererClientQt()
{
}
@@ -108,23 +97,24 @@ void ContentRendererClientQt::RenderThreadStarted()
{
content::RenderThread *renderThread = content::RenderThread::Get();
m_visitedLinkSlave.reset(new visitedlink::VisitedLinkSlave);
- m_webCacheObserver.reset(new web_cache::WebCacheRenderProcessObserver());
- m_renderProcessObserver.reset(new RenderProcessObserverQt());
+ m_webCacheImpl.reset(new web_cache::WebCacheImpl());
renderThread->AddObserver(m_visitedLinkSlave.data());
- renderThread->AddObserver(m_webCacheObserver.data());
renderThread->AddObserver(UserResourceController::instance());
- renderThread->AddObserver(m_renderProcessObserver.data());
#if defined(ENABLE_SPELLCHECK)
m_spellCheck.reset(new SpellCheck());
renderThread->AddObserver(m_spellCheck.data());
#endif
+
+ blink::WebString qrcScheme(base::ASCIIToUTF16(kQrcSchemeQt));
+ // mark qrc as a secure scheme (avoids deprecation warnings)
+ blink::WebSecurityPolicy::registerURLSchemeAsSecure(qrcScheme);
}
void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view)
{
// RenderViewObservers destroy themselves with their RenderView.
- new RenderViewObserverQt(render_view, m_webCacheObserver.data());
+ new RenderViewObserverQt(render_view, m_webCacheImpl.data());
new WebChannelIPCTransport(render_view);
UserResourceController::instance()->renderViewCreated(render_view);
#if defined(ENABLE_SPELLCHECK)
@@ -133,9 +123,8 @@ void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view
#if defined(ENABLE_BASIC_PRINTING)
new printing::PrintWebViewHelper(
- render_view,
- scoped_ptr<printing::PrintWebViewHelper::Delegate>(
- new PrintWebViewHelperDelegateQt()));
+ render_view,
+ base::WrapUnique(new PrintWebViewHelperDelegateQt()));
#endif // defined(ENABLE_BASIC_PRINTING)
}
@@ -144,14 +133,26 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_fr
new QtWebEngineCore::RenderFrameObserverQt(render_frame);
}
+void ContentRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame* render_frame)
+{
+ if (WebChannelIPCTransport *transport = WebChannelIPCTransport::Get(render_frame->GetRenderView()))
+ transport->RunScriptsAtDocumentStart(render_frame);
+ UserResourceController::instance()->RunScriptsAtDocumentStart(render_frame);
+}
+
+void ContentRendererClientQt::RunScriptsAtDocumentEnd(content::RenderFrame* render_frame)
+{
+ UserResourceController::instance()->RunScriptsAtDocumentEnd(render_frame);
+}
+
bool ContentRendererClientQt::HasErrorPage(int httpStatusCode, std::string *errorDomain)
{
// Use an internal error page, if we have one for the status code.
- if (!LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain, httpStatusCode)) {
+ if (!error_page::LocalizedError::HasStrings(error_page::LocalizedError::kHttpErrorDomain, httpStatusCode)) {
return false;
}
- *errorDomain = LocalizedError::kHttpErrorDomain;
+ *errorDomain = error_page::LocalizedError::kHttpErrorDomain;
return true;
}
@@ -173,9 +174,10 @@ void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderFrame* re
const std::string locale = content::RenderThread::Get()->GetLocale();
// TODO(elproxy): We could potentially get better diagnostics here by first calling
// NetErrorHelper::GetErrorStringsForDnsProbe, but that one is harder to untangle.
- LocalizedError::GetStrings(error.reason, error.domain.utf8(), error.unreachableURL, isPost
- , error.staleCopyInCache && !isPost, false, error_page::OfflinePageStatus::NONE, locale, renderFrame->GetRenderView()->GetAcceptLanguages()
- , scoped_ptr<error_page::ErrorPageParams>(), &errorStrings);
+
+ error_page::LocalizedError::GetStrings(error.reason, error.domain.utf8(), error.unreachableURL, isPost
+ , error.staleCopyInCache && !isPost, false, false, locale
+ , std::unique_ptr<error_page::ErrorPageParams>(), &errorStrings);
resourceId = IDR_NET_ERROR_HTML;
@@ -187,7 +189,7 @@ void ContentRendererClientQt::GetNavigationErrorStrings(content::RenderFrame* re
}
if (errorDescription)
- *errorDescription = LocalizedError::GetErrorDetails(error.domain.utf8(), error.reason, isPost);
+ *errorDescription = error_page::LocalizedError::GetErrorDetails(error.domain.utf8(), error.reason, isPost);
}
unsigned long long ContentRendererClientQt::VisitedLinkHash(const char *canonicalUrl, size_t length)
@@ -206,6 +208,8 @@ bool ContentRendererClientQt::IsLinkVisited(unsigned long long linkHash)
// found in the LICENSE file.
#if defined(ENABLE_PEPPER_CDMS)
+static const char kExternalClearKeyPepperType[] = "application/x-ppapi-clearkey-cdm";
+
static bool IsPepperCdmAvailable(const std::string& pepper_type,
std::vector<base::string16>* additional_param_names,
std::vector<base::string16>* additional_param_values)
@@ -221,21 +225,94 @@ static bool IsPepperCdmAvailable(const std::string& pepper_type,
return is_available;
}
+// KeySystemProperties implementation for external Clear Key systems.
+class ExternalClearKeyProperties : public media::KeySystemProperties
+{
+public:
+ explicit ExternalClearKeyProperties(const std::string& key_system_name)
+ : key_system_name_(key_system_name) {}
+
+ std::string GetKeySystemName() const override { return key_system_name_; }
+ bool IsSupportedInitDataType(media::EmeInitDataType init_data_type) const override
+ {
+ switch (init_data_type) {
+ case media::EmeInitDataType::WEBM:
+ case media::EmeInitDataType::KEYIDS:
+ return true;
+
+ case media::EmeInitDataType::CENC:
+#if defined(USE_PROPRIETARY_CODECS)
+ return true;
+#else
+ return false;
+#endif // defined(USE_PROPRIETARY_CODECS)
+
+ case media::EmeInitDataType::UNKNOWN:
+ return false;
+ }
+ NOTREACHED();
+ return false;
+ }
+
+ media::SupportedCodecs GetSupportedCodecs() const override
+ {
+#if defined(USE_PROPRIETARY_CODECS)
+ return media::EME_CODEC_MP4_ALL | media::EME_CODEC_WEBM_ALL;
+#else
+ return media::EME_CODEC_WEBM_ALL;
+#endif
+ }
+
+ media::EmeConfigRule GetRobustnessConfigRule(
+ media::EmeMediaType media_type,
+ const std::string& requested_robustness) const override
+ {
+ return requested_robustness.empty() ? media::EmeConfigRule::SUPPORTED
+ : media::EmeConfigRule::NOT_SUPPORTED;
+ }
+
+ // Persistent license sessions are faked.
+ media::EmeSessionTypeSupport GetPersistentLicenseSessionSupport() const override
+ {
+ return media::EmeSessionTypeSupport::SUPPORTED;
+ }
+
+ media::EmeSessionTypeSupport GetPersistentReleaseMessageSessionSupport() const override {
+ return media::EmeSessionTypeSupport::NOT_SUPPORTED;
+ }
+
+ media::EmeFeatureSupport GetPersistentStateSupport() const override
+ {
+ return media::EmeFeatureSupport::REQUESTABLE;
+ }
+
+ media::EmeFeatureSupport GetDistinctiveIdentifierSupport() const override
+ {
+ return media::EmeFeatureSupport::NOT_SUPPORTED;
+ }
+
+ std::string GetPepperType() const override
+ {
+ return kExternalClearKeyPepperType;
+ }
+
+private:
+ const std::string key_system_name_;
+};
+
// External Clear Key (used for testing).
-static void AddExternalClearKey(std::vector<media::KeySystemInfo>* concrete_key_systems)
+static void AddExternalClearKey(std::vector<std::unique_ptr<media::KeySystemProperties>>* concrete_key_systems)
{
- static const char kExternalClearKeyKeySystem[] =
- "org.chromium.externalclearkey";
- static const char kExternalClearKeyDecryptOnlyKeySystem[] =
- "org.chromium.externalclearkey.decryptonly";
- static const char kExternalClearKeyFileIOTestKeySystem[] =
- "org.chromium.externalclearkey.fileiotest";
- static const char kExternalClearKeyInitializeFailKeySystem[] =
- "org.chromium.externalclearkey.initializefail";
- static const char kExternalClearKeyCrashKeySystem[] =
- "org.chromium.externalclearkey.crash";
- static const char kExternalClearKeyPepperType[] =
- "application/x-ppapi-clearkey-cdm";
+ static const char kExternalClearKeyKeySystem[] =
+ "org.chromium.externalclearkey";
+ static const char kExternalClearKeyDecryptOnlyKeySystem[] =
+ "org.chromium.externalclearkey.decryptonly";
+ static const char kExternalClearKeyFileIOTestKeySystem[] =
+ "org.chromium.externalclearkey.fileiotest";
+ static const char kExternalClearKeyInitializeFailKeySystem[] =
+ "org.chromium.externalclearkey.initializefail";
+ static const char kExternalClearKeyCrashKeySystem[] =
+ "org.chromium.externalclearkey.crash";
std::vector<base::string16> additional_param_names;
std::vector<base::string16> additional_param_values;
@@ -244,53 +321,31 @@ static void AddExternalClearKey(std::vector<media::KeySystemInfo>* concrete_key_
&additional_param_values))
return;
- media::KeySystemInfo info;
- info.key_system = kExternalClearKeyKeySystem;
-
- info.supported_init_data_types =
- media::kInitDataTypeMaskWebM | media::kInitDataTypeMaskKeyIds;
- info.supported_codecs = media::EME_CODEC_WEBM_ALL;
-#if defined(USE_PROPRIETARY_CODECS)
- info.supported_init_data_types |= media::kInitDataTypeMaskCenc;
- info.supported_codecs |= media::EME_CODEC_MP4_ALL;
-#endif // defined(USE_PROPRIETARY_CODECS)
-
- info.max_audio_robustness = media::EmeRobustness::EMPTY;
- info.max_video_robustness = media::EmeRobustness::EMPTY;
-
- // Persistent sessions are faked.
- info.persistent_license_support = media::EmeSessionTypeSupport::SUPPORTED;
- info.persistent_release_message_support =
- media::EmeSessionTypeSupport::NOT_SUPPORTED;
- info.persistent_state_support = media::EmeFeatureSupport::REQUESTABLE;
- info.distinctive_identifier_support = media::EmeFeatureSupport::NOT_SUPPORTED;
-
- info.pepper_type = kExternalClearKeyPepperType;
-
- concrete_key_systems->push_back(info);
+ concrete_key_systems->emplace_back(
+ new ExternalClearKeyProperties(kExternalClearKeyKeySystem));
// Add support of decrypt-only mode in ClearKeyCdm.
- info.key_system = kExternalClearKeyDecryptOnlyKeySystem;
- concrete_key_systems->push_back(info);
+ concrete_key_systems->emplace_back(
+ new ExternalClearKeyProperties(kExternalClearKeyDecryptOnlyKeySystem));
// A key system that triggers FileIO test in ClearKeyCdm.
- info.key_system = kExternalClearKeyFileIOTestKeySystem;
- concrete_key_systems->push_back(info);
+ concrete_key_systems->emplace_back(
+ new ExternalClearKeyProperties(kExternalClearKeyFileIOTestKeySystem));
// A key system that Chrome thinks is supported by ClearKeyCdm, but actually
// will be refused by ClearKeyCdm. This is to test the CDM initialization
// failure case.
- info.key_system = kExternalClearKeyInitializeFailKeySystem;
- concrete_key_systems->push_back(info);
+ concrete_key_systems->emplace_back(
+ new ExternalClearKeyProperties(kExternalClearKeyInitializeFailKeySystem));
// A key system that triggers a crash in ClearKeyCdm.
- info.key_system = kExternalClearKeyCrashKeySystem;
- concrete_key_systems->push_back(info);
+ concrete_key_systems->emplace_back(
+ new ExternalClearKeyProperties(kExternalClearKeyCrashKeySystem));
}
#if defined(WIDEVINE_CDM_AVAILABLE)
-static void AddPepperBasedWidevine(std::vector<media::KeySystemInfo>* concrete_key_systems)
+static void AddPepperBasedWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>> *concrete_key_systems)
{
//#if defined(WIDEVINE_CDM_MIN_GLIBC_VERSION)
// Version glibc_version(gnu_get_libc_version());
@@ -319,26 +374,26 @@ static void AddPepperBasedWidevine(std::vector<media::KeySystemInfo>* concrete_k
supported_codecs |= media::EME_CODEC_MP4_AAC;
#endif // defined(USE_PROPRIETARY_CODECS)
- cdm::AddWidevineWithCodecs(
- cdm::WIDEVINE, supported_codecs,
- media::EmeRobustness::SW_SECURE_CRYPTO, // Maximum audio robustness.
- media::EmeRobustness::SW_SECURE_DECODE, // Maximum video robustness.
+ using Robustness = cdm::WidevineKeySystemProperties::Robustness;
+ concrete_key_systems->emplace_back(new cdm::WidevineKeySystemProperties(
+ supported_codecs,
+ Robustness::SW_SECURE_CRYPTO, // Maximum audio robustness.
+ Robustness::SW_SECURE_DECODE, // Maximum video robustness.
media::EmeSessionTypeSupport::NOT_SUPPORTED, // persistent-license.
media::EmeSessionTypeSupport::NOT_SUPPORTED, // persistent-release-message.
- media::EmeFeatureSupport::REQUESTABLE, // Persistent state.
- media::EmeFeatureSupport::NOT_SUPPORTED, // Distinctive identifier.
- concrete_key_systems);
+ media::EmeFeatureSupport::REQUESTABLE, // Persistent state.
+ media::EmeFeatureSupport::NOT_SUPPORTED)); // Distinctive identifier.
}
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#endif // defined(ENABLE_PEPPER_CDMS)
-void ContentRendererClientQt::AddKeySystems(std::vector<media::KeySystemInfo>* key_systems_info)
+void ContentRendererClientQt::AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>> *key_systems)
{
#if defined(ENABLE_PEPPER_CDMS)
- AddExternalClearKey(key_systems_info);
+ AddExternalClearKey(key_systems);
#if defined(WIDEVINE_CDM_AVAILABLE)
- AddPepperBasedWidevine(key_systems_info);
+ AddPepperBasedWidevine(key_systems);
#endif // defined(WIDEVINE_CDM_AVAILABLE)
#endif // defined(ENABLE_PEPPER_CDMS)
}
diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h
index d475c7801..72b4e4061 100644
--- a/src/core/renderer/content_renderer_client_qt.h
+++ b/src/core/renderer/content_renderer_client_qt.h
@@ -44,16 +44,12 @@
#include <QtGlobal>
#include <QScopedPointer>
-namespace content {
-class RenderProcessObserver;
-}
-
namespace visitedlink {
class VisitedLinkSlave;
}
namespace web_cache {
-class WebCacheRenderProcessObserver;
+class WebCacheImpl;
}
#if defined(ENABLE_SPELLCHECK)
@@ -76,12 +72,14 @@ public:
virtual unsigned long long VisitedLinkHash(const char *canonicalUrl, size_t length) Q_DECL_OVERRIDE;
virtual bool IsLinkVisited(unsigned long long linkHash) Q_DECL_OVERRIDE;
- virtual void AddKeySystems(std::vector<media::KeySystemInfo>* key_systems) Q_DECL_OVERRIDE;
+ virtual void AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) Q_DECL_OVERRIDE;
+
+ virtual void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) Q_DECL_OVERRIDE;
+ virtual void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) Q_DECL_OVERRIDE;
private:
QScopedPointer<visitedlink::VisitedLinkSlave> m_visitedLinkSlave;
- QScopedPointer<web_cache::WebCacheRenderProcessObserver> m_webCacheObserver;
- QScopedPointer<content::RenderProcessObserver> m_renderProcessObserver;
+ QScopedPointer<web_cache::WebCacheImpl> m_webCacheImpl;
#if defined(ENABLE_SPELLCHECK)
QScopedPointer<SpellCheck> m_spellCheck;
#endif
diff --git a/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp b/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp
deleted file mode 100644
index c1782844d..000000000
--- a/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.cpp
+++ /dev/null
@@ -1,401 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// based on chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc
-// Copyright (c) 2012 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 file.
-
-#include "pepper_flash_clipboard_message_filter_qt.h"
-
-#include "base/pickle.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/public/browser/browser_thread.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_macros.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/c/private/ppb_flash_clipboard.h"
-#include "ppapi/host/dispatch_host_message.h"
-#include "ppapi/host/host_message_context.h"
-#include "ppapi/host/ppapi_host.h"
-#include "ppapi/proxy/ppapi_messages.h"
-#include "ppapi/proxy/resource_message_params.h"
-#include "ui/base/clipboard/scoped_clipboard_writer.h"
-
-using content::BrowserThread;
-
-namespace QtWebEngineCore {
-
-namespace {
-
-const size_t kMaxClipboardWriteSize = 1000000;
-
-ui::ClipboardType ConvertClipboardType(uint32_t type)
-{
- switch (type) {
- case PP_FLASH_CLIPBOARD_TYPE_STANDARD:
- return ui::CLIPBOARD_TYPE_COPY_PASTE;
- case PP_FLASH_CLIPBOARD_TYPE_SELECTION:
- return ui::CLIPBOARD_TYPE_SELECTION;
- }
- NOTREACHED();
- return ui::CLIPBOARD_TYPE_COPY_PASTE;
-}
-
-// Functions to pack/unpack custom data from a pickle. See the header file for
-// more detail on custom formats in Pepper.
-// TODO(raymes): Currently pepper custom formats are stored in their own
-// native format type. However we should be able to store them in the same way
-// as "Web Custom" formats are. This would allow clipboard data to be shared
-// between pepper applications and web applications. However currently web apps
-// assume all data that is placed on the clipboard is UTF16 and pepper allows
-// arbitrary data so this change would require some reworking of the chrome
-// clipboard interface for custom data.
-bool JumpToFormatInPickle(const base::string16& format, base::PickleIterator* iter)
-{
- size_t size = 0;
- if (!iter->ReadSizeT(&size))
- return false;
- for (size_t i = 0; i < size; ++i) {
- base::string16 stored_format;
- if (!iter->ReadString16(&stored_format))
- return false;
- if (stored_format == format)
- return true;
- int skip_length;
- if (!iter->ReadLength(&skip_length))
- return false;
- if (!iter->SkipBytes(skip_length))
- return false;
- }
- return false;
-}
-
-bool IsFormatAvailableInPickle(const base::string16& format, const base::Pickle& pickle)
-{
- base::PickleIterator iter(pickle);
- return JumpToFormatInPickle(format, &iter);
-}
-
-std::string ReadDataFromPickle(const base::string16& format, const base::Pickle& pickle)
-{
- std::string result;
- base::PickleIterator iter(pickle);
- if (!JumpToFormatInPickle(format, &iter) || !iter.ReadString(&result))
- return std::string();
- return result;
-}
-
-bool WriteDataToPickle(const std::map<base::string16, std::string>& data, base::Pickle* pickle)
-{
- pickle->WriteSizeT(data.size());
- for (std::map<base::string16, std::string>::const_iterator it = data.begin(); it != data.end(); ++it) {
- if (!pickle->WriteString16(it->first))
- return false;
- if (!pickle->WriteString(it->second))
- return false;
- }
- return true;
-}
-
-} // namespace
-
-PepperFlashClipboardMessageFilter::PepperFlashClipboardMessageFilter() {}
-
-PepperFlashClipboardMessageFilter::~PepperFlashClipboardMessageFilter() {}
-
-scoped_refptr<base::TaskRunner>
-PepperFlashClipboardMessageFilter::OverrideTaskRunnerForMessage(const IPC::Message& msg)
-{
- // Clipboard writes should always occur on the UI thread due to the
- // restrictions of various platform APIs. In general, the clipboard is not
- // thread-safe, so all clipboard calls should be serviced from the UI thread.
- if (msg.type() == PpapiHostMsg_FlashClipboard_WriteData::ID)
- return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
-
- // Windows needs clipboard reads to be serviced from the IO thread because
- // these are sync IPCs which can result in deadlocks with plugins if serviced
- // from the UI thread. Note that Windows clipboard calls ARE thread-safe so it
- // is ok for reads and writes to be serviced from different threads.
-#if !defined(OS_WIN)
- return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
-#else
- return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
-#endif
-}
-
-int32_t PepperFlashClipboardMessageFilter::OnResourceMessageReceived(const IPC::Message& msg,
- ppapi::host::HostMessageContext* context)
-{
- PPAPI_BEGIN_MESSAGE_MAP(PepperFlashClipboardMessageFilter, msg)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_RegisterCustomFormat,
- OnMsgRegisterCustomFormat)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_IsFormatAvailable,
- OnMsgIsFormatAvailable)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_ReadData,
- OnMsgReadData)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_WriteData,
- OnMsgWriteData)
- PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_FlashClipboard_GetSequenceNumber,
- OnMsgGetSequenceNumber)
- PPAPI_END_MESSAGE_MAP()
- return PP_ERROR_FAILED;
-}
-
-int32_t PepperFlashClipboardMessageFilter::OnMsgRegisterCustomFormat(
- ppapi::host::HostMessageContext* host_context,
- const std::string& format_name)
-{
- uint32_t format = m_custom_formats.RegisterFormat(format_name);
- if (format == PP_FLASH_CLIPBOARD_FORMAT_INVALID)
- return PP_ERROR_FAILED;
- host_context->reply_msg = PpapiPluginMsg_FlashClipboard_RegisterCustomFormatReply(format);
- return PP_OK;
-}
-
-int32_t PepperFlashClipboardMessageFilter::OnMsgIsFormatAvailable(
- ppapi::host::HostMessageContext* host_context,
- uint32_t clipboard_type,
- uint32_t format)
-{
- if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) {
- NOTIMPLEMENTED();
- return PP_ERROR_FAILED;
- }
-
- ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- ui::ClipboardType type = ConvertClipboardType(clipboard_type);
- bool available = false;
- switch (format) {
- case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: {
- bool plain = clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(), type);
- bool plainw = clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(), type);
- available = plain || plainw;
- break;
- }
- case PP_FLASH_CLIPBOARD_FORMAT_HTML:
- available = clipboard->IsFormatAvailable(ui::Clipboard::GetHtmlFormatType(), type);
- break;
- case PP_FLASH_CLIPBOARD_FORMAT_RTF:
- available = clipboard->IsFormatAvailable(ui::Clipboard::GetRtfFormatType(), type);
- break;
- case PP_FLASH_CLIPBOARD_FORMAT_INVALID:
- break;
- default:
- if (m_custom_formats.IsFormatRegistered(format)) {
- std::string format_name = m_custom_formats.GetFormatName(format);
- std::string clipboard_data;
- clipboard->ReadData(ui::Clipboard::GetPepperCustomDataFormatType(), &clipboard_data);
- base::Pickle pickle(clipboard_data.data(), clipboard_data.size());
- available = IsFormatAvailableInPickle(base::UTF8ToUTF16(format_name), pickle);
- }
- break;
- }
-
- return available ? PP_OK : PP_ERROR_FAILED;
-}
-
-int32_t PepperFlashClipboardMessageFilter::OnMsgReadData(
- ppapi::host::HostMessageContext* host_context,
- uint32_t clipboard_type,
- uint32_t format)
-{
- if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) {
- NOTIMPLEMENTED();
- return PP_ERROR_FAILED;
- }
-
- ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- ui::ClipboardType type = ConvertClipboardType(clipboard_type);
- std::string clipboard_string;
- int32_t result = PP_ERROR_FAILED;
- switch (format) {
- case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: {
- if (clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextWFormatType(), type)) {
- base::string16 text;
- clipboard->ReadText(type, &text);
- if (!text.empty()) {
- result = PP_OK;
- clipboard_string = base::UTF16ToUTF8(text);
- break;
- }
- }
- // If the PlainTextW format isn't available or is empty, take the
- // ASCII text format.
- if (clipboard->IsFormatAvailable(ui::Clipboard::GetPlainTextFormatType(), type)) {
- result = PP_OK;
- clipboard->ReadAsciiText(type, &clipboard_string);
- }
- break;
- }
- case PP_FLASH_CLIPBOARD_FORMAT_HTML: {
- if (!clipboard->IsFormatAvailable(ui::Clipboard::GetHtmlFormatType(), type)) {
- break;
- }
-
- base::string16 html;
- std::string url;
- uint32_t fragment_start;
- uint32_t fragment_end;
- clipboard->ReadHTML(type, &html, &url, &fragment_start, &fragment_end);
- result = PP_OK;
- clipboard_string = base::UTF16ToUTF8(html.substr(fragment_start, fragment_end - fragment_start));
- break;
- }
- case PP_FLASH_CLIPBOARD_FORMAT_RTF: {
- if (!clipboard->IsFormatAvailable(ui::Clipboard::GetRtfFormatType(), type)) {
- break;
- }
- result = PP_OK;
- clipboard->ReadRTF(type, &clipboard_string);
- break;
- }
- case PP_FLASH_CLIPBOARD_FORMAT_INVALID:
- break;
- default:
- if (m_custom_formats.IsFormatRegistered(format)) {
- base::string16 format_name =
- base::UTF8ToUTF16(m_custom_formats.GetFormatName(format));
- std::string clipboard_data;
- clipboard->ReadData(ui::Clipboard::GetPepperCustomDataFormatType(),
- &clipboard_data);
- base::Pickle pickle(clipboard_data.data(), clipboard_data.size());
- if (IsFormatAvailableInPickle(format_name, pickle)) {
- result = PP_OK;
- clipboard_string = ReadDataFromPickle(format_name, pickle);
- }
- }
- break;
- }
-
- if (result == PP_OK) {
- host_context->reply_msg = PpapiPluginMsg_FlashClipboard_ReadDataReply(clipboard_string);
- }
- return result;
-}
-
-int32_t PepperFlashClipboardMessageFilter::OnMsgWriteData(
- ppapi::host::HostMessageContext* host_context,
- uint32_t clipboard_type,
- const std::vector<uint32_t>& formats,
- const std::vector<std::string>& data)
-{
- if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) {
- NOTIMPLEMENTED();
- return PP_ERROR_FAILED;
- }
- if (formats.size() != data.size())
- return PP_ERROR_FAILED;
-
- ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- ui::ClipboardType type = ConvertClipboardType(clipboard_type);
- // If no formats are passed in clear the clipboard.
- if (formats.size() == 0) {
- clipboard->Clear(type);
- return PP_OK;
- }
-
- ui::ScopedClipboardWriter scw(type);
- std::map<base::string16, std::string> custom_data_map;
- int32_t res = PP_OK;
- for (uint32_t i = 0; i < formats.size(); ++i) {
- if (data[i].length() > kMaxClipboardWriteSize) {
- res = PP_ERROR_NOSPACE;
- break;
- }
-
- switch (formats[i]) {
- case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT:
- scw.WriteText(base::UTF8ToUTF16(data[i]));
- break;
- case PP_FLASH_CLIPBOARD_FORMAT_HTML:
- scw.WriteHTML(base::UTF8ToUTF16(data[i]), std::string());
- break;
- case PP_FLASH_CLIPBOARD_FORMAT_RTF:
- scw.WriteRTF(data[i]);
- break;
- case PP_FLASH_CLIPBOARD_FORMAT_INVALID:
- res = PP_ERROR_BADARGUMENT;
- break;
- default:
- if (m_custom_formats.IsFormatRegistered(formats[i])) {
- std::string format_name = m_custom_formats.GetFormatName(formats[i]);
- custom_data_map[base::UTF8ToUTF16(format_name)] = data[i];
- } else {
- // Invalid format.
- res = PP_ERROR_BADARGUMENT;
- break;
- }
- }
-
- if (res != PP_OK)
- break;
- }
-
- if (custom_data_map.size() > 0) {
- base::Pickle pickle;
- if (WriteDataToPickle(custom_data_map, &pickle)) {
- scw.WritePickledData(pickle, ui::Clipboard::GetPepperCustomDataFormatType());
- } else {
- res = PP_ERROR_BADARGUMENT;
- }
- }
-
- if (res != PP_OK) {
- // Need to clear the objects so nothing is written.
- scw.Reset();
- }
-
- return res;
-}
-
-int32_t PepperFlashClipboardMessageFilter::OnMsgGetSequenceNumber(
- ppapi::host::HostMessageContext* host_context,
- uint32_t clipboard_type)
-{
- if (clipboard_type != PP_FLASH_CLIPBOARD_TYPE_STANDARD) {
- NOTIMPLEMENTED();
- return PP_ERROR_FAILED;
- }
-
- ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
- ui::ClipboardType type = ConvertClipboardType(clipboard_type);
- int64_t sequence_number = clipboard->GetSequenceNumber(type);
- host_context->reply_msg = PpapiPluginMsg_FlashClipboard_GetSequenceNumberReply(sequence_number);
- return PP_OK;
-}
-
-} // namespace QtWebEngineCore
diff --git a/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.h b/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.h
deleted file mode 100644
index c00e668ea..000000000
--- a/src/core/renderer/pepper/pepper_flash_clipboard_message_filter_qt.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 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.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 later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-// based on chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h
-// Copyright (c) 2012 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 file.
-
-#ifndef PEPPER_FLASH_CLIPBOARD_MESSAGE_FILTER_QT_H
-#define PEPPER_FLASH_CLIPBOARD_MESSAGE_FILTER_QT_H
-
-#include <string>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "ppapi/host/resource_message_filter.h"
-#include "ppapi/shared_impl/flash_clipboard_format_registry.h"
-
-namespace ppapi {
-namespace host {
-struct HostMessageContext;
-}
-}
-
-namespace ui {
-class ScopedClipboardWriter;
-}
-
-namespace QtWebEngineCore {
-
-// Resource message filter for accessing the clipboard in Pepper. Pepper
-// supports reading/writing custom formats from the clipboard. Currently, all
-// custom formats that are read/written from the clipboard through pepper are
-// stored in a single real clipboard format (in the same way the "web custom"
-// clipboard formats are). This is done so that we don't have to have use real
-// clipboard types for each custom clipboard format which may be a limited
-// resource on a particular platform.
-class PepperFlashClipboardMessageFilter : public ppapi::host::ResourceMessageFilter {
-public:
- PepperFlashClipboardMessageFilter();
-
-protected:
- // ppapi::host::ResourceMessageFilter overrides.
- scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(const IPC::Message& msg) override;
- int32_t OnResourceMessageReceived(const IPC::Message& msg, ppapi::host::HostMessageContext* context) override;
-
-private:
- ~PepperFlashClipboardMessageFilter() override;
-
- int32_t OnMsgRegisterCustomFormat(ppapi::host::HostMessageContext* host_context, const std::string& format_name);
- int32_t OnMsgIsFormatAvailable(ppapi::host::HostMessageContext* host_context,
- uint32_t clipboard_type,
- uint32_t format);
- int32_t OnMsgReadData(ppapi::host::HostMessageContext* host_context,
- uint32_t clipoard_type,
- uint32_t format);
- int32_t OnMsgWriteData(ppapi::host::HostMessageContext* host_context,
- uint32_t clipboard_type,
- const std::vector<uint32_t>& formats,
- const std::vector<std::string>& data);
- int32_t OnMsgGetSequenceNumber(ppapi::host::HostMessageContext* host_context,
- uint32_t clipboard_type);
-
- int32_t WriteClipboardDataItem(uint32_t format,
- const std::string& data,
- ui::ScopedClipboardWriter* scw);
-
- ppapi::FlashClipboardFormatRegistry m_custom_formats;
-
- DISALLOW_COPY_AND_ASSIGN(PepperFlashClipboardMessageFilter);
-};
-
-} // namespace QtWebEngineCore
-
-#endif // PEPPER_FLASH_CLIPBOARD_MESSAGE_FILTER_QT_H
diff --git a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp
index 37ce4b5f3..a46454407 100644
--- a/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp
+++ b/src/core/renderer/pepper/pepper_flash_renderer_host_qt.cpp
@@ -250,6 +250,83 @@ int32_t PepperFlashRendererHostQt::OnDrawGlyphs(
params.glyph_indices.empty())
return PP_ERROR_FAILED;
+ int style = SkTypeface::kNormal;
+ if (static_cast<PP_BrowserFont_Trusted_Weight>(params.font_desc.weight) >= PP_BROWSERFONT_TRUSTED_WEIGHT_BOLD)
+ style |= SkTypeface::kBold;
+ if (params.font_desc.italic)
+ style |= SkTypeface::kItalic;
+ sk_sp<SkTypeface> typeface(SkTypeface::MakeFromName(params.font_desc.face.c_str(), SkFontStyle::FromOldStyle(style)));
+ if (!typeface)
+ return PP_ERROR_FAILED;
+
+ EnterResourceNoLock<PPB_ImageData_API> enter(params.image_data.host_resource(), true);
+ if (enter.failed())
+ return PP_ERROR_FAILED;
+
+ PPB_ImageData_API* image = static_cast<PPB_ImageData_API*>(enter.object());
+ SkCanvas* canvas = image->GetCanvas();
+ bool needs_unmapping = false;
+ if (!canvas) {
+ needs_unmapping = true;
+ image->Map();
+ canvas = image->GetCanvas();
+ if (!canvas)
+ return PP_ERROR_FAILED; // Failure mapping.
+ }
+
+ SkAutoCanvasRestore acr(canvas, true);
+
+ // Clip is applied in pixels before the transform.
+ SkRect clip_rect = {
+ SkIntToScalar(params.clip.point.x), SkIntToScalar(params.clip.point.y),
+ SkIntToScalar(params.clip.point.x + params.clip.size.width),
+ SkIntToScalar(params.clip.point.y + params.clip.size.height)};
+ canvas->clipRect(clip_rect);
+
+ SkMatrix matrix;
+ matrix.set(SkMatrix::kMScaleX, SkFloatToScalar(params.transformation[0][0]));
+ matrix.set(SkMatrix::kMSkewX, SkFloatToScalar(params.transformation[0][1]));
+ matrix.set(SkMatrix::kMTransX, SkFloatToScalar(params.transformation[0][2]));
+ matrix.set(SkMatrix::kMSkewY, SkFloatToScalar(params.transformation[1][0]));
+ matrix.set(SkMatrix::kMScaleY, SkFloatToScalar(params.transformation[1][1]));
+ matrix.set(SkMatrix::kMTransY, SkFloatToScalar(params.transformation[1][2]));
+ matrix.set(SkMatrix::kMPersp0, SkFloatToScalar(params.transformation[2][0]));
+ matrix.set(SkMatrix::kMPersp1, SkFloatToScalar(params.transformation[2][1]));
+ matrix.set(SkMatrix::kMPersp2, SkFloatToScalar(params.transformation[2][2]));
+ canvas->concat(matrix);
+
+ SkPaint paint;
+ paint.setColor(params.color);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setAntiAlias(true);
+ paint.setHinting(SkPaint::kFull_Hinting);
+ paint.setTextSize(SkIntToScalar(params.font_desc.size));
+ paint.setTypeface(std::move(typeface));
+ if (params.allow_subpixel_aa) {
+ paint.setSubpixelText(true);
+ paint.setLCDRenderText(true);
+ }
+
+ SkScalar x = SkIntToScalar(params.position.x);
+ SkScalar y = SkIntToScalar(params.position.y);
+
+ // Build up the skia advances.
+ size_t glyph_count = params.glyph_indices.size();
+ if (glyph_count) {
+ std::vector<SkPoint> sk_positions(glyph_count);
+ for (uint32_t i = 0; i < glyph_count; i++) {
+ sk_positions[i].set(x, y);
+ x += SkFloatToScalar(params.glyph_advances[i].x);
+ y += SkFloatToScalar(params.glyph_advances[i].y);
+ }
+
+ canvas->drawPosText(
+ &params.glyph_indices[0], glyph_count * 2, &sk_positions[0], paint);
+ }
+
+ if (needs_unmapping)
+ image->Unmap();
+
return PP_OK;
}
diff --git a/src/core/renderer/pepper/pepper_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_host_factory_qt.cpp
index 9b7236d8a..4a25e7756 100644
--- a/src/core/renderer/pepper/pepper_host_factory_qt.cpp
+++ b/src/core/renderer/pepper/pepper_host_factory_qt.cpp
@@ -44,7 +44,9 @@
#include "pepper_host_factory_qt.h"
+#include "base/memory/ptr_util.h"
#include "build/build_config.h"
+#include "chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h"
#include "content/public/browser/browser_ppapi_host.h"
#include "ppapi/host/message_filter_host.h"
#include "ppapi/host/ppapi_host.h"
@@ -53,7 +55,6 @@
#include "ppapi/shared_impl/ppapi_permissions.h"
#include "pepper_flash_browser_host_qt.h"
-#include "pepper_flash_clipboard_message_filter_qt.h"
#include "pepper_isolated_file_system_message_filter.h"
using ppapi::host::MessageFilterHost;
@@ -68,7 +69,7 @@ PepperHostFactoryQt::PepperHostFactoryQt(content::BrowserPpapiHost* host)
PepperHostFactoryQt::~PepperHostFactoryQt() {}
-scoped_ptr<ppapi::host::ResourceHost> PepperHostFactoryQt::CreateResourceHost(ppapi::host::PpapiHost* host,
+std::unique_ptr<ppapi::host::ResourceHost> PepperHostFactoryQt::CreateResourceHost(ppapi::host::PpapiHost* host,
PP_Resource resource,
PP_Instance instance,
const IPC::Message& message)
@@ -77,16 +78,16 @@ scoped_ptr<ppapi::host::ResourceHost> PepperHostFactoryQt::CreateResourceHost(pp
if (!host_->IsValidInstance(instance))
- return scoped_ptr<ppapi::host::ResourceHost>();
+ return nullptr;
// Flash interfaces.
if (host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_FLASH)) {
switch (message.type()) {
case PpapiHostMsg_Flash_Create::ID:
- return scoped_ptr<ppapi::host::ResourceHost>(new PepperFlashBrowserHostQt(host_, instance, resource));
+ return base::WrapUnique(new PepperFlashBrowserHostQt(host_, instance, resource));
case PpapiHostMsg_FlashClipboard_Create::ID: {
- scoped_refptr<ResourceMessageFilter> clipboard_filter(new PepperFlashClipboardMessageFilter);
- return scoped_ptr<ppapi::host::ResourceHost>(new MessageFilterHost(
+ scoped_refptr<ResourceMessageFilter> clipboard_filter(new chrome::PepperFlashClipboardMessageFilter);
+ return base::WrapUnique(new MessageFilterHost(
host_->GetPpapiHost(), instance, resource, clipboard_filter));
}
}
@@ -101,11 +102,12 @@ scoped_ptr<ppapi::host::ResourceHost> PepperHostFactoryQt::CreateResourceHost(pp
if (message.type() == PpapiHostMsg_IsolatedFileSystem_Create::ID) {
PepperIsolatedFileSystemMessageFilter* isolated_fs_filter = PepperIsolatedFileSystemMessageFilter::Create(instance, host_);
if (!isolated_fs_filter)
- return scoped_ptr<ppapi::host::ResourceHost>();
- return scoped_ptr<ppapi::host::ResourceHost>(new MessageFilterHost(host, instance, resource, isolated_fs_filter));
+ return nullptr;
+ return base::WrapUnique(
+ new MessageFilterHost(host_->GetPpapiHost(), instance, resource, isolated_fs_filter));
}
- return scoped_ptr<ppapi::host::ResourceHost>();
+ return nullptr;
}
} // namespace QtWebEngineCore
diff --git a/src/core/renderer/pepper/pepper_host_factory_qt.h b/src/core/renderer/pepper/pepper_host_factory_qt.h
index e73e097c0..0446cf9e3 100644
--- a/src/core/renderer/pepper/pepper_host_factory_qt.h
+++ b/src/core/renderer/pepper/pepper_host_factory_qt.h
@@ -57,7 +57,7 @@ public:
explicit PepperHostFactoryQt(content::BrowserPpapiHost* host);
~PepperHostFactoryQt() override;
- virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
+ virtual std::unique_ptr<ppapi::host::ResourceHost> CreateResourceHost(
ppapi::host::PpapiHost* host,
PP_Resource resource,
PP_Instance instance,
diff --git a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp
index 636ca12f1..febde84f7 100644
--- a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp
+++ b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.cpp
@@ -44,6 +44,9 @@
#include "pepper_renderer_host_factory_qt.h"
#include "pepper_flash_renderer_host_qt.h"
+
+#include "base/memory/ptr_util.h"
+#include "chrome/renderer/pepper/pepper_flash_font_file_host.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/host/resource_host.h"
@@ -63,7 +66,7 @@ PepperRendererHostFactoryQt::~PepperRendererHostFactoryQt()
{
}
-scoped_ptr<ppapi::host::ResourceHost> PepperRendererHostFactoryQt::CreateResourceHost(
+std::unique_ptr<ppapi::host::ResourceHost> PepperRendererHostFactoryQt::CreateResourceHost(
ppapi::host::PpapiHost* host,
PP_Resource resource,
PP_Instance instance,
@@ -72,16 +75,47 @@ scoped_ptr<ppapi::host::ResourceHost> PepperRendererHostFactoryQt::CreateResourc
DCHECK_EQ(host_->GetPpapiHost(), host);
if (!host_->IsValidInstance(instance))
- return scoped_ptr<ppapi::host::ResourceHost>();
+ return nullptr;
+
+ if (host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_FLASH)) {
+ switch (message.type()) {
+ case PpapiHostMsg_Flash_Create::ID:
+ return base::WrapUnique(new PepperFlashRendererHostQt(host_, instance, resource));
+ case PpapiHostMsg_FlashFullscreen_Create::ID:
+ case PpapiHostMsg_FlashMenu_Create::ID:
+ // Not implemented
+ break;
+ }
+ }
+ // TODO(raymes): PDF also needs access to the FlashFontFileHost currently.
+ // We should either rename PPB_FlashFont_File to PPB_FontFile_Private or get
+ // rid of its use in PDF if possible.
if (host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_FLASH)
- && message.type() == PpapiHostMsg_Flash_Create::ID)
- return scoped_ptr<ppapi::host::ResourceHost>(
- new PepperFlashRendererHostQt(host_,
- instance,
- resource));
+ || host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE)) {
+ switch (message.type()) {
+ case PpapiHostMsg_FlashFontFile_Create::ID: {
+ ppapi::proxy::SerializedFontDescription description;
+ PP_PrivateFontCharset charset;
+ if (ppapi::UnpackMessage<PpapiHostMsg_FlashFontFile_Create>(message, &description, &charset))
+ return base::WrapUnique(new PepperFlashFontFileHost(host_, instance, resource, description, charset));
+ break;
+ }
+ case PpapiHostMsg_FlashDRM_Create::ID:
+ // Not implemented
+ break;
+ }
+ }
+
+ if (host_->GetPpapiHost()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE)) {
+ switch (message.type()) {
+ case PpapiHostMsg_PDF_Create::ID:
+ // Not implemented
+ break;
+ }
+ }
- return scoped_ptr<ppapi::host::ResourceHost>();
+ return nullptr;
}
} // QtWebEngineCore
diff --git a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.h b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.h
index bc472a7c6..ec3440a08 100644
--- a/src/core/renderer/pepper/pepper_renderer_host_factory_qt.h
+++ b/src/core/renderer/pepper/pepper_renderer_host_factory_qt.h
@@ -56,7 +56,7 @@ public:
~PepperRendererHostFactoryQt();
// HostFactory.
- scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
+ std::unique_ptr<ppapi::host::ResourceHost> CreateResourceHost(
ppapi::host::PpapiHost* host,
PP_Resource resource,
PP_Instance instance,
diff --git a/src/core/renderer/render_frame_observer_qt.cpp b/src/core/renderer/render_frame_observer_qt.cpp
index f2285f298..77bc89f67 100644
--- a/src/core/renderer/render_frame_observer_qt.cpp
+++ b/src/core/renderer/render_frame_observer_qt.cpp
@@ -44,11 +44,12 @@
#include "render_frame_observer_qt.h"
+#include "base/memory/ptr_util.h"
+#include "chrome/renderer/pepper/pepper_shared_memory_message_filter.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "ppapi/host/ppapi_host.h"
#include "renderer/pepper/pepper_renderer_host_factory_qt.h"
-#include "renderer/pepper/pepper_flash_renderer_host_qt.h"
namespace QtWebEngineCore {
@@ -65,8 +66,9 @@ RenderFrameObserverQt::~RenderFrameObserverQt()
void RenderFrameObserverQt::DidCreatePepperPlugin(content::RendererPpapiHost* host)
{
host->GetPpapiHost()->AddHostFactoryFilter(
- scoped_ptr<ppapi::host::HostFactory>(
- new PepperRendererHostFactoryQt(host)));
+ base::WrapUnique(new PepperRendererHostFactoryQt(host)));
+ host->GetPpapiHost()->AddInstanceMessageFilter(
+ base::WrapUnique(new PepperSharedMemoryMessageFilter(host)));
}
#endif
diff --git a/src/core/renderer/render_frame_observer_qt.h b/src/core/renderer/render_frame_observer_qt.h
index b1d59d8c5..c59b7babc 100644
--- a/src/core/renderer/render_frame_observer_qt.h
+++ b/src/core/renderer/render_frame_observer_qt.h
@@ -58,6 +58,7 @@ public:
#if defined(ENABLE_PLUGINS)
void DidCreatePepperPlugin(content::RendererPpapiHost* host) override;
#endif
+ void OnDestruct() override { }
private:
DISALLOW_COPY_AND_ASSIGN(RenderFrameObserverQt);
diff --git a/src/core/renderer/render_view_observer_qt.cpp b/src/core/renderer/render_view_observer_qt.cpp
index 4b44a9bd9..393b4752c 100644
--- a/src/core/renderer/render_view_observer_qt.cpp
+++ b/src/core/renderer/render_view_observer_qt.cpp
@@ -41,40 +41,46 @@
#include "common/qt_messages.h"
-#include "components/web_cache/renderer/web_cache_render_process_observer.h"
+#include "components/web_cache/renderer/web_cache_impl.h"
#include "content/public/renderer/render_view.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebFrameContentDumper.h"
+#include "third_party/WebKit/public/web/WebFrameWidget.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
RenderViewObserverQt::RenderViewObserverQt(
content::RenderView* render_view,
- web_cache::WebCacheRenderProcessObserver* web_cache_render_process_observer)
+ web_cache::WebCacheImpl* web_cache_impl)
: content::RenderViewObserver(render_view)
- , m_web_cache_render_process_observer(web_cache_render_process_observer)
+ , m_web_cache_impl(web_cache_impl)
{
}
void RenderViewObserverQt::onFetchDocumentMarkup(quint64 requestId)
{
- Send(new RenderViewObserverHostQt_DidFetchDocumentMarkup(
- routing_id(),
- requestId,
- render_view()->GetWebView()->mainFrame()->contentAsMarkup()));
+ blink::WebString markup;
+ if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame())
+ markup = blink::WebFrameContentDumper::dumpAsMarkup(
+ static_cast<blink::WebLocalFrame*>(render_view()->GetWebView()->mainFrame()));
+ Send(new RenderViewObserverHostQt_DidFetchDocumentMarkup(routing_id(), requestId, markup));
}
void RenderViewObserverQt::onFetchDocumentInnerText(quint64 requestId)
{
- Send(new RenderViewObserverHostQt_DidFetchDocumentInnerText(
- routing_id(),
- requestId,
- render_view()->GetWebView()->mainFrame()->contentAsText(std::numeric_limits<std::size_t>::max())));
+ blink::WebString text;
+ if (render_view()->GetWebView()->mainFrame()->isWebLocalFrame())
+ text = blink::WebFrameContentDumper::dumpWebViewAsText(
+ render_view()->GetWebView(),
+ std::numeric_limits<std::size_t>::max());
+ Send(new RenderViewObserverHostQt_DidFetchDocumentInnerText(routing_id(), requestId, text));
}
void RenderViewObserverQt::onSetBackgroundColor(quint32 color)
{
- render_view()->GetWebView()->setBaseBackgroundColor(color);
+ render_view()->GetWebFrameWidget()->setBaseBackgroundColor(color);
}
void RenderViewObserverQt::OnFirstVisuallyNonEmptyLayout()
@@ -96,6 +102,6 @@ bool RenderViewObserverQt::OnMessageReceived(const IPC::Message& message)
void RenderViewObserverQt::Navigate(const GURL &)
{
- if (m_web_cache_render_process_observer)
- m_web_cache_render_process_observer->ExecutePendingClearCache();
+ if (m_web_cache_impl)
+ m_web_cache_impl->ExecutePendingClearCache();
}
diff --git a/src/core/renderer/render_view_observer_qt.h b/src/core/renderer/render_view_observer_qt.h
index 4839ae064..b62c815af 100644
--- a/src/core/renderer/render_view_observer_qt.h
+++ b/src/core/renderer/render_view_observer_qt.h
@@ -44,13 +44,13 @@
#include <QtGlobal>
namespace web_cache {
-class WebCacheRenderProcessObserver;
+class WebCacheImpl;
}
class RenderViewObserverQt : public content::RenderViewObserver {
public:
RenderViewObserverQt(content::RenderView* render_view,
- web_cache::WebCacheRenderProcessObserver* web_cache_render_process_observer);
+ web_cache::WebCacheImpl* web_cache_impl);
private:
void onFetchDocumentMarkup(quint64 requestId);
@@ -58,11 +58,12 @@ private:
void onSetBackgroundColor(quint32 color);
void OnFirstVisuallyNonEmptyLayout() Q_DECL_OVERRIDE;
+ void OnDestruct() Q_DECL_OVERRIDE { }
virtual bool OnMessageReceived(const IPC::Message& message) Q_DECL_OVERRIDE;
virtual void Navigate(const GURL& url) Q_DECL_OVERRIDE;
- web_cache::WebCacheRenderProcessObserver* m_web_cache_render_process_observer;
+ web_cache::WebCacheImpl* m_web_cache_impl;
DISALLOW_COPY_AND_ASSIGN(RenderViewObserverQt);
};
diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp
index 30a04958f..8c603b805 100644
--- a/src/core/renderer/user_resource_controller.cpp
+++ b/src/core/renderer/user_resource_controller.cpp
@@ -39,8 +39,12 @@
#include "user_resource_controller.h"
+#include "base/strings/pattern.h"
+#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/render_view_observer.h"
+#include "extensions/common/url_pattern.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebView.h"
@@ -48,6 +52,8 @@
#include "common/qt_messages.h"
#include "common/user_script_data.h"
+#include "type_conversion.h"
+#include "user_script.h"
Q_GLOBAL_STATIC(UserResourceController, qt_webengine_userResourceController)
@@ -56,13 +62,46 @@ static content::RenderView * const globalScriptsIndex = 0;
// Scripts meant to run after the load event will be run 500ms after DOMContentLoaded if the load event doesn't come within that delay.
static const int afterLoadTimeout = 500;
+static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url) {
+ // Logic taken from Chromium (extensions/common/user_script.cc)
+ bool matchFound;
+ if (!scriptData.urlPatterns.empty()) {
+ matchFound = false;
+ for (auto it = scriptData.urlPatterns.begin(), end = scriptData.urlPatterns.end(); it != end; ++it) {
+ URLPattern urlPattern(QtWebEngineCore::UserScript::validUserScriptSchemes(), *it);
+ if (urlPattern.MatchesURL(url))
+ matchFound = true;
+ }
+ if (!matchFound)
+ return false;
+ }
+
+ if (!scriptData.globs.empty()) {
+ matchFound = false;
+ for (auto it = scriptData.globs.begin(), end = scriptData.globs.end(); it != end; ++it) {
+ if (base::MatchPattern(url.spec(), *it))
+ matchFound = true;
+ }
+ if (!matchFound)
+ return false;
+ }
+
+ if (!scriptData.excludeGlobs.empty()) {
+ for (auto it = scriptData.excludeGlobs.begin(), end = scriptData.excludeGlobs.end(); it != end; ++it) {
+ if (base::MatchPattern(url.spec(), *it))
+ return false;
+ }
+ }
+
+ return true;
+}
+
class UserResourceController::RenderViewObserverHelper : public content::RenderViewObserver
{
public:
RenderViewObserverHelper(content::RenderView *);
private:
// RenderViewObserver implementation.
- virtual void DidCreateDocumentElement(blink::WebLocalFrame* frame) Q_DECL_OVERRIDE;
virtual void DidFinishDocumentLoad(blink::WebLocalFrame* frame) Q_DECL_OVERRIDE;
virtual void DidFinishLoad(blink::WebLocalFrame* frame) Q_DECL_OVERRIDE;
virtual void DidStartProvisionalLoad(blink::WebLocalFrame* frame) Q_DECL_OVERRIDE;
@@ -82,17 +121,25 @@ void UserResourceController::RenderViewObserverHelper::runScripts(UserScriptData
{
if (p == UserScriptData::AfterLoad && !m_pendingFrames.remove(frame))
return;
+
+ UserResourceController::instance()->runScripts(p, frame);
+}
+
+void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame)
+{
content::RenderView *renderView = content::RenderView::FromWebView(frame->view());
const bool isMainFrame = (frame == renderView->GetWebView()->mainFrame());
- QList<uint64_t> scriptsToRun = UserResourceController::instance()->m_viewUserScriptMap.value(globalScriptsIndex).toList();
- scriptsToRun.append(UserResourceController::instance()->m_viewUserScriptMap.value(renderView).toList());
+ QList<uint64_t> scriptsToRun = m_viewUserScriptMap.value(globalScriptsIndex).toList();
+ scriptsToRun.append(m_viewUserScriptMap.value(renderView).toList());
Q_FOREACH (uint64_t id, scriptsToRun) {
- const UserScriptData &script = UserResourceController::instance()->m_scripts.value(id);
+ const UserScriptData &script = m_scripts.value(id);
if (script.injectionPoint != p
|| (!script.injectForSubframes && !isMainFrame))
continue;
+ if (!scriptMatchesURL(script, frame->document().url()))
+ continue;
blink::WebScriptSource source(blink::WebString::fromUTF8(script.source), script.url);
if (script.worldId)
frame->executeScriptInIsolatedWorld(script.worldId, &source, /*numSources = */1, /*contentScriptExtentsionGroup = */ 0);
@@ -101,20 +148,23 @@ void UserResourceController::RenderViewObserverHelper::runScripts(UserScriptData
}
}
+void UserResourceController::RunScriptsAtDocumentStart(content::RenderFrame *render_frame)
+{
+ runScripts(UserScriptData::DocumentElementCreation, render_frame->GetWebFrame());
+}
-UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *renderView)
- : content::RenderViewObserver(renderView)
+void UserResourceController::RunScriptsAtDocumentEnd(content::RenderFrame *render_frame)
{
+ runScripts(UserScriptData::DocumentLoadFinished, render_frame->GetWebFrame());
}
-void UserResourceController::RenderViewObserverHelper::DidCreateDocumentElement(blink::WebLocalFrame *frame)
+UserResourceController::RenderViewObserverHelper::RenderViewObserverHelper(content::RenderView *renderView)
+ : content::RenderViewObserver(renderView)
{
- runScripts(UserScriptData::DocumentElementCreation, frame);
}
void UserResourceController::RenderViewObserverHelper::DidFinishDocumentLoad(blink::WebLocalFrame *frame)
{
- runScripts(UserScriptData::DocumentLoadFinished, frame);
m_pendingFrames.insert(frame);
base::MessageLoop::current()->PostDelayedTask(FROM_HERE, base::Bind(&UserResourceController::RenderViewObserverHelper::runScripts,
base::Unretained(this), UserScriptData::AfterLoad, frame),
diff --git a/src/core/renderer/user_resource_controller.h b/src/core/renderer/user_resource_controller.h
index bd3d0ba49..d0b5088d6 100644
--- a/src/core/renderer/user_resource_controller.h
+++ b/src/core/renderer/user_resource_controller.h
@@ -40,7 +40,7 @@
#ifndef USER_RESOURCE_CONTROLLER_H
#define USER_RESOURCE_CONTROLLER_H
-#include "content/public/renderer/render_process_observer.h"
+#include "content/public/renderer/render_thread_observer.h"
#include "common/user_script_data.h"
@@ -48,12 +48,16 @@
#include <QtCore/QHash>
#include <QtCore/QSet>
+namespace blink {
+class WebLocalFrame;
+}
+
namespace content {
+class RenderFrame;
class RenderView;
}
-
-class UserResourceController : public content::RenderProcessObserver {
+class UserResourceController : public content::RenderThreadObserver {
public:
static UserResourceController *instance();
@@ -64,22 +68,29 @@ public:
void removeScriptForView(const UserScriptData &, content::RenderView *);
void clearScriptsForView(content::RenderView *);
+ void RunScriptsAtDocumentStart(content::RenderFrame *render_frame);
+ void RunScriptsAtDocumentEnd(content::RenderFrame *render_frame);
+
private:
Q_DISABLE_COPY(UserResourceController)
class RenderViewObserverHelper;
// RenderProcessObserver implementation.
- virtual bool OnControlMessageReceived(const IPC::Message &message) Q_DECL_OVERRIDE;
+ bool OnControlMessageReceived(const IPC::Message &message) override;
void onAddScript(const UserScriptData &);
void onRemoveScript(const UserScriptData &);
void onClearScripts();
+ void runScripts(UserScriptData::InjectionPoint, blink::WebLocalFrame *);
+
typedef QSet<uint64_t> UserScriptSet;
typedef QHash<const content::RenderView *, UserScriptSet> ViewUserScriptMap;
ViewUserScriptMap m_viewUserScriptMap;
QHash<uint64_t, UserScriptData> m_scripts;
+
+ friend class RenderViewObserverHelper;
};
#endif // USER_RESOURCE_CONTROLLER_H
diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp
index 6bbbe28bd..3a44bb182 100644
--- a/src/core/renderer/web_channel_ipc_transport.cpp
+++ b/src/core/renderer/web_channel_ipc_transport.cpp
@@ -44,6 +44,7 @@
#include "common/qt_messages.h"
+#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "gin/arguments.h"
#include "gin/handle.h"
@@ -153,11 +154,22 @@ content::RenderView *WebChannelTransport::GetRenderView(v8::Isolate *isolate)
WebChannelIPCTransport::WebChannelIPCTransport(content::RenderView *renderView)
: content::RenderViewObserver(renderView)
+ , content::RenderViewObserverTracker<WebChannelIPCTransport>(renderView)
, m_installed(false)
, m_installedWorldId(0)
{
}
+void WebChannelIPCTransport::RunScriptsAtDocumentStart(content::RenderFrame *render_frame)
+{
+ // JavaScript run before this point doesn't stick, and needs to be redone.
+ // ### FIXME: we should try no even installing before
+ blink::WebLocalFrame *frame = render_frame->GetWebFrame();
+ if (m_installed && render_frame->IsMainFrame())
+ WebChannelTransport::Install(frame, m_installedWorldId);
+}
+
+
void WebChannelIPCTransport::installWebChannel(uint worldId)
{
blink::WebView *webView = render_view()->GetWebView();
@@ -170,6 +182,7 @@ void WebChannelIPCTransport::installWebChannel(uint worldId)
void WebChannelIPCTransport::uninstallWebChannel(uint worldId)
{
+ Q_ASSERT(worldId = m_installedWorldId);
blink::WebView *webView = render_view()->GetWebView();
if (!webView)
return;
@@ -222,13 +235,6 @@ void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> &
frame->callFunctionEvenIfScriptDisabled(callback, webChannelObjectValue->ToObject(), argc, argv);
}
-void WebChannelIPCTransport::DidCreateDocumentElement(blink::WebLocalFrame* frame)
-{
- blink::WebFrame* main_frame = render_view()->GetWebView()->mainFrame();
- if (m_installed && frame == main_frame)
- WebChannelTransport::Install(frame, m_installedWorldId);
-}
-
bool WebChannelIPCTransport::OnMessageReceived(const IPC::Message &message)
{
bool handled = true;
diff --git a/src/core/renderer/web_channel_ipc_transport.h b/src/core/renderer/web_channel_ipc_transport.h
index fcee13bda..e949d1c99 100644
--- a/src/core/renderer/web_channel_ipc_transport.h
+++ b/src/core/renderer/web_channel_ipc_transport.h
@@ -42,24 +42,33 @@
#include "base/values.h"
#include "content/public/renderer/render_view_observer.h"
+#include "content/public/renderer/render_view_observer_tracker.h"
#include <QtCore/qcompilerdetection.h>
+namespace content {
+class RenderFrame;
+}
+
namespace v8 {
class Extension;
}
namespace QtWebEngineCore {
-class WebChannelIPCTransport : public content::RenderViewObserver {
+class WebChannelIPCTransport : public content::RenderViewObserver
+ , public content::RenderViewObserverTracker<WebChannelIPCTransport>
+{
public:
WebChannelIPCTransport(content::RenderView *);
+ void RunScriptsAtDocumentStart(content::RenderFrame *render_frame);
+
private:
void dispatchWebChannelMessage(const std::vector<char> &binaryJSON, uint worldId);
void installWebChannel(uint worldId);
void uninstallWebChannel(uint worldId);
- virtual void DidCreateDocumentElement(blink::WebLocalFrame* frame) override;
virtual bool OnMessageReceived(const IPC::Message &message) Q_DECL_OVERRIDE;
+ virtual void OnDestruct() Q_DECL_OVERRIDE { }
bool m_installed;
uint m_installedWorldId;
diff --git a/src/core/resource_bundle_qt.cpp b/src/core/resource_bundle_qt.cpp
index fa5c04524..5f5cead96 100644
--- a/src/core/resource_bundle_qt.cpp
+++ b/src/core/resource_bundle_qt.cpp
@@ -38,10 +38,20 @@
****************************************************************************/
#include "base/command_line.h"
+#include "base/metrics/histogram.h"
#include "content/public/common/content_switches.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/data_pack.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_switches.h"
+
#include "web_engine_library_info.h"
+#if defined(OS_LINUX)
+#include "base/posix/global_descriptors.h"
+#include "global_descriptors_qt.h"
+#endif
+
namespace ui {
void ResourceBundle::LoadCommonResources()
@@ -53,11 +63,69 @@ void ResourceBundle::LoadCommonResources()
AddOptionalDataPackFromPath(WebEngineLibraryInfo::getPath(QT_RESOURCES_DEVTOOLS_PAK), SCALE_FACTOR_NONE);
}
-gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id, ImageRTL rtl)
+gfx::Image& ResourceBundle::GetNativeImageNamed(int resource_id)
{
LOG(WARNING) << "Unable to load image with id " << resource_id;
NOTREACHED(); // Want to assert in debug mode.
return GetEmptyImage();
}
+bool ResourceBundle::LocaleDataPakExists(const std::string& locale)
+{
+#if defined(OS_LINUX)
+ base::CommandLine *parsed_command_line = base::CommandLine::ForCurrentProcess();
+ std::string process_type = parsed_command_line->GetSwitchValueASCII(switches::kProcessType);
+ if (process_type == switches::kRendererProcess) {
+ // The Renderer Process is sandboxed thus only one locale is available in it.
+ // The particular one is passed by the --lang command line option.
+ if (!parsed_command_line->HasSwitch(switches::kLang) || parsed_command_line->GetSwitchValueASCII(switches::kLang) != locale)
+ return false;
+
+ auto global_descriptors = base::GlobalDescriptors::GetInstance();
+ return global_descriptors->MaybeGet(kWebEngineLocale) != -1;
+ }
+#endif
+
+ return !GetLocaleFilePath(locale, true).empty();
+}
+
+std::string ResourceBundle::LoadLocaleResources(const std::string& pref_locale)
+{
+ DCHECK(!locale_resources_data_.get()) << "locale.pak already loaded";
+
+ std::string app_locale = l10n_util::GetApplicationLocale(pref_locale);
+
+#if defined(OS_LINUX)
+ int locale_fd = base::GlobalDescriptors::GetInstance()->MaybeGet(kWebEngineLocale);
+ if (locale_fd > -1) {
+ std::unique_ptr<DataPack> data_pack(new DataPack(SCALE_FACTOR_100P));
+ data_pack->LoadFromFile(base::File(locale_fd));
+ locale_resources_data_.reset(data_pack.release());
+ return app_locale;
+ }
+#endif
+
+ base::FilePath locale_file_path = GetOverriddenPakPath();
+ if (locale_file_path.empty())
+ locale_file_path = GetLocaleFilePath(app_locale, true);
+
+ if (locale_file_path.empty()) {
+ // It's possible that there is no locale.pak.
+ LOG(WARNING) << "locale_file_path.empty() for locale " << app_locale;
+ return std::string();
+ }
+
+ std::unique_ptr<DataPack> data_pack(new DataPack(SCALE_FACTOR_100P));
+ if (!data_pack->LoadFromPath(locale_file_path)) {
+ UMA_HISTOGRAM_ENUMERATION("ResourceBundle.LoadLocaleResourcesError",
+ logging::GetLastSystemErrorCode(), 16000);
+ LOG(ERROR) << "failed to load locale.pak";
+ NOTREACHED();
+ return std::string();
+ }
+
+ locale_resources_data_.reset(data_pack.release());
+ return app_locale;
+}
+
} // namespace ui
diff --git a/src/core/resource_context_qt.cpp b/src/core/resource_context_qt.cpp
index 5cb217605..1ab1ea223 100644
--- a/src/core/resource_context_qt.cpp
+++ b/src/core/resource_context_qt.cpp
@@ -39,6 +39,7 @@
#include "resource_context_qt.h"
+#include "content/public/browser/storage_partition.h"
#include "net/url_request/url_request_context_getter.h"
#include "browser_context_qt.h"
@@ -53,6 +54,8 @@ net::HostResolver *ResourceContextQt::GetHostResolver()
net::URLRequestContext* ResourceContextQt::GetRequestContext()
{
Q_ASSERT(context);
+ // FIXME: This is the only remaining use of GetRequestContext(),
+ // but we are on the wrong thread for calling BrowserContext::GetDefaultStoragePartition
return context->GetRequestContext()->GetURLRequestContext();
}
diff --git a/src/core/resource_dispatcher_host_delegate_qt.cpp b/src/core/resource_dispatcher_host_delegate_qt.cpp
index af8b02e1b..16a4e7265 100644
--- a/src/core/resource_dispatcher_host_delegate_qt.cpp
+++ b/src/core/resource_dispatcher_host_delegate_qt.cpp
@@ -151,7 +151,8 @@ static void LaunchURL(const GURL& url, int render_process_id,
bool ResourceDispatcherHostDelegateQt::HandleExternalProtocol(const GURL& url, int child_id,
const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
- bool is_main_frame, ui::PageTransition page_transition, bool has_user_gesture)
+ bool is_main_frame, ui::PageTransition page_transition, bool has_user_gesture,
+ content::ResourceContext* /*resource_context*/)
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
// We don't want to launch external applications unless it is based on a user action
diff --git a/src/core/resource_dispatcher_host_delegate_qt.h b/src/core/resource_dispatcher_host_delegate_qt.h
index 6481c6438..a8a65cfb7 100644
--- a/src/core/resource_dispatcher_host_delegate_qt.h
+++ b/src/core/resource_dispatcher_host_delegate_qt.h
@@ -89,10 +89,10 @@ private:
class ResourceDispatcherHostDelegateQt : public content::ResourceDispatcherHostDelegate {
public:
- virtual bool HandleExternalProtocol(const GURL& url,int child_id,
- const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
- bool is_main_frame, ui::PageTransition page_transition, bool has_user_gesture)
- Q_DECL_OVERRIDE;
+ bool HandleExternalProtocol(const GURL& url, int child_id,
+ const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
+ bool is_main_frame, ui::PageTransition page_transition, bool has_user_gesture,
+ content::ResourceContext* resource_context) override;
virtual content::ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(net::AuthChallengeInfo *authInfo, net::URLRequest *request) Q_DECL_OVERRIDE;
};
diff --git a/src/core/resources/resources.gyp b/src/core/resources/resources.gyp
index 618b4d355..8b7d520a9 100644
--- a/src/core/resources/resources.gyp
+++ b/src/core/resources/resources.gyp
@@ -20,6 +20,7 @@
'dependencies': [
'<(chromium_src_dir)/content/app/strings/content_strings.gyp:content_strings',
'<(chromium_src_dir)/content/browser/devtools/devtools_resources.gyp:devtools_resources',
+ '<(chromium_src_dir)/components/components_resources.gyp:components_resources',
'<(chromium_src_dir)/components/components_strings.gyp:components_strings',
'<(chromium_src_dir)/third_party/WebKit/public/blink_resources.gyp:blink_resources',
'<(qtwebengine_root)/src/core/chrome_qt.gyp:chrome_resources',
@@ -30,6 +31,7 @@
'variables': {
'pak_inputs': [
'<(SHARED_INTERMEDIATE_DIR)/net/net_resources.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/components/components_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/content_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_resources.pak',
'<(SHARED_INTERMEDIATE_DIR)/ui/resources/webui_resources.pak',
@@ -45,6 +47,7 @@
'variables': {
'pak_inputs': [
'<(SHARED_INTERMEDIATE_DIR)/ui/resources/ui_resources_100_percent.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/components/components_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/app/resources/content_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/chrome/renderer_resources_100_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_image_resources_100_percent.pak',
@@ -60,6 +63,7 @@
'variables': {
'pak_inputs': [
'<(SHARED_INTERMEDIATE_DIR)/ui/resources/ui_resources_200_percent.pak',
+ '<(SHARED_INTERMEDIATE_DIR)/components/components_resources_200_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/content/app/resources/content_resources_200_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/chrome/renderer_resources_200_percent.pak',
'<(SHARED_INTERMEDIATE_DIR)/blink/public/resources/blink_image_resources_200_percent.pak',
diff --git a/src/core/surface_factory_qt.cpp b/src/core/surface_factory_qt.cpp
index 48c91bfcf..97a304730 100644
--- a/src/core/surface_factory_qt.cpp
+++ b/src/core/surface_factory_qt.cpp
@@ -85,7 +85,7 @@ bool SurfaceFactoryQt::LoadEGLGLES2Bindings(AddGLLibraryCallback add_gl_library,
if (!gles2Library)
return false;
- gfx::GLGetProcAddressProc get_proc_address = reinterpret_cast<gfx::GLGetProcAddressProc>(base::GetFunctionPointerFromNativeLibrary(eglLibrary, "eglGetProcAddress"));
+ gl::GLGetProcAddressProc get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(base::GetFunctionPointerFromNativeLibrary(eglLibrary, "eglGetProcAddress"));
if (!get_proc_address) {
LOG(ERROR) << "eglGetProcAddress not found.";
base::UnloadNativeLibrary(eglLibrary);
@@ -93,9 +93,9 @@ bool SurfaceFactoryQt::LoadEGLGLES2Bindings(AddGLLibraryCallback add_gl_library,
return false;
}
- gfx::SetGLGetProcAddressProc(get_proc_address);
- gfx::AddGLNativeLibrary(eglLibrary);
- gfx::AddGLNativeLibrary(gles2Library);
+ gl::SetGLGetProcAddressProc(get_proc_address);
+ gl::AddGLNativeLibrary(eglLibrary);
+ gl::AddGLNativeLibrary(gles2Library);
return true;
}
diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp
index ef220b86c..a7b5ee831 100644
--- a/src/core/type_conversion.cpp
+++ b/src/core/type_conversion.cpp
@@ -50,6 +50,8 @@ QImage toQImage(const SkBitmap &bitmap)
QImage image;
switch (bitmap.colorType()) {
case kUnknown_SkColorType:
+ case kRGBA_F16_SkColorType:
+ qWarning("Unknown or unsupported skia image format");
break;
case kAlpha_8_SkColorType:
image = toQImage(bitmap, QImage::Format_Alpha8);
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index e96a544e5..ed02a9db9 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -60,7 +60,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPixelRef.h"
-#include "third_party/skia/include/utils/SkMatrix44.h"
+#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "url/gurl.h"
diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp
index bf32c75a4..25f7e36e6 100644
--- a/src/core/url_request_context_getter_qt.cpp
+++ b/src/core/url_request_context_getter_qt.cpp
@@ -40,6 +40,7 @@
#include "url_request_context_getter_qt.h"
#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/threading/worker_pool.h"
#include "base/threading/sequenced_worker_pool.h"
@@ -48,6 +49,9 @@
#include "content/public/common/content_switches.h"
#include "net/base/cache_type.h"
#include "net/cert/cert_verifier.h"
+#include "net/cert/ct_log_verifier.h"
+#include "net/cert/ct_policy_enforcer.h"
+#include "net/cert/multi_log_ct_verifier.h"
#include "net/disk_cache/disk_cache.h"
#include "net/dns/host_resolver.h"
#include "net/dns/mapped_host_resolver.h"
@@ -216,6 +220,7 @@ void URLRequestContextGetterQt::generateStorage()
cancelAllUrlRequests();
// we need to get rid of dangling pointer due to coming storage deletion
m_urlRequestContext->set_http_transaction_factory(0);
+ m_httpNetworkSession.reset();
}
m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get()));
@@ -224,8 +229,10 @@ void URLRequestContextGetterQt::generateStorage()
Q_ASSERT(proxyConfigService);
m_storage->set_cert_verifier(net::CertVerifier::CreateDefault());
+ m_storage->set_cert_transparency_verifier(base::WrapUnique(new net::MultiLogCTVerifier()));
+ m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::CTPolicyEnforcer));
- scoped_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
+ std::unique_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
// The System Proxy Resolver has issues on Windows with unconfigured network cards,
// which is why we want to use the v8 one
@@ -233,7 +240,7 @@ void URLRequestContextGetterQt::generateStorage()
m_dhcpProxyScriptFetcherFactory.reset(new net::DhcpProxyScriptFetcherFactory);
m_storage->set_proxy_service(net::CreateProxyServiceUsingV8ProxyResolver(
- scoped_ptr<net::ProxyConfigService>(proxyConfigService),
+ std::unique_ptr<net::ProxyConfigService>(proxyConfigService),
new net::ProxyScriptFetcherImpl(m_urlRequestContext.get()),
m_dhcpProxyScriptFetcherFactory->Create(m_urlRequestContext.get()),
host_resolver.get(),
@@ -241,10 +248,10 @@ void URLRequestContextGetterQt::generateStorage()
m_networkDelegate.get()));
m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults);
- m_storage->set_transport_security_state(scoped_ptr<net::TransportSecurityState>(new net::TransportSecurityState()));
+ m_storage->set_transport_security_state(std::unique_ptr<net::TransportSecurityState>(new net::TransportSecurityState()));
m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
- m_storage->set_http_server_properties(scoped_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl));
+ m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl));
// Give |m_storage| ownership at the end in case it's |mapped_host_resolver|.
m_storage->set_host_resolver(std::move(host_resolver));
@@ -283,7 +290,7 @@ void URLRequestContextGetterQt::generateCookieStore()
}
m_storage->set_channel_id_service(
- scoped_ptr<net::ChannelIDService>(new net::ChannelIDService(
+ base::WrapUnique(new net::ChannelIDService(
new net::DefaultChannelIDStore(channel_id_db.get()),
base::WorkerPool::GetTaskRunner(true))));
@@ -291,7 +298,7 @@ void URLRequestContextGetterQt::generateCookieStore()
m_storage->set_cookie_store(0);
m_cookieDelegate->setCookieMonster(0);
- net::CookieStore* cookieStore = 0;
+ std::unique_ptr<net::CookieStore> cookieStore;
switch (m_persistentCookiesPolicy) {
case BrowserContextAdapter::NoPersistentCookies:
cookieStore =
@@ -321,10 +328,13 @@ void URLRequestContextGetterQt::generateCookieStore()
);
break;
}
- m_storage->set_cookie_store(cookieStore);
- net::CookieMonster * const cookieMonster = cookieStore->GetCookieMonster();
- cookieMonster->SetCookieableSchemes(kCookieableSchemes, arraysize(kCookieableSchemes));
+ net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get());
+ cookieStore->SetChannelIDServiceID(m_urlRequestContext->channel_id_service()->GetUniqueID());
+ m_storage->set_cookie_store(std::move(cookieStore));
+
+ const std::vector<std::string> cookieableSchemes(kCookieableSchemes, kCookieableSchemes + arraysize(kCookieableSchemes));
+ cookieMonster->SetCookieableSchemes(cookieableSchemes);
m_cookieDelegate->setCookieMonster(cookieMonster);
}
@@ -351,7 +361,7 @@ void URLRequestContextGetterQt::generateUserAgent()
QMutexLocker lock(&m_mutex);
m_updateUserAgent = true;
- m_storage->set_http_user_agent_settings(scoped_ptr<net::HttpUserAgentSettings>(
+ m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>(
new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), m_httpUserAgent.toStdString())));
}
@@ -406,9 +416,7 @@ static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &f
return false;
if (first.http_auth_handler_factory != second.http_auth_handler_factory)
return false;
- if (first.network_delegate != second.network_delegate)
- return false;
- if (first.http_server_properties.get() != second.http_server_properties.get())
+ if (first.http_server_properties != second.http_server_properties)
return false;
if (first.ignore_certificate_errors != second.ignore_certificate_errors)
return false;
@@ -430,10 +438,11 @@ net::HttpNetworkSession::Params URLRequestContextGetterQt::generateNetworkSessio
network_session_params.proxy_service = m_urlRequestContext->proxy_service();
network_session_params.ssl_config_service = m_urlRequestContext->ssl_config_service();
network_session_params.http_auth_handler_factory = m_urlRequestContext->http_auth_handler_factory();
- network_session_params.network_delegate = m_networkDelegate.get();
network_session_params.http_server_properties = m_urlRequestContext->http_server_properties();
network_session_params.ignore_certificate_errors = m_ignoreCertificateErrors;
network_session_params.host_resolver = m_urlRequestContext->host_resolver();
+ network_session_params.cert_transparency_verifier = m_urlRequestContext->cert_transparency_verifier();
+ network_session_params.ct_policy_enforcer = m_urlRequestContext->ct_policy_enforcer();
return network_session_params;
}
@@ -482,9 +491,9 @@ void URLRequestContextGetterQt::generateHttpCache()
m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params));
}
- cache = new net::HttpCache(m_httpNetworkSession.get(), scoped_ptr<net::HttpCache::DefaultBackend>(main_backend), false);
+ cache = new net::HttpCache(m_httpNetworkSession.get(), std::unique_ptr<net::HttpCache::DefaultBackend>(main_backend), false);
- m_storage->set_http_transaction_factory(scoped_ptr<net::HttpCache>(cache));
+ m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache));
}
void URLRequestContextGetterQt::clearHttpCache()
@@ -513,36 +522,36 @@ void URLRequestContextGetterQt::generateJobFactory()
QMutexLocker lock(&m_mutex);
m_updateJobFactory = false;
- scoped_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl());
+ std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl());
{
// Chromium has a few protocol handlers ready for us, only pick blob: and throw away the rest.
content::ProtocolHandlerMap::iterator it = m_protocolHandlers.find(url::kBlobScheme);
Q_ASSERT(it != m_protocolHandlers.end());
- jobFactory->SetProtocolHandler(it->first, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(it->second.release()));
+ jobFactory->SetProtocolHandler(it->first, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(it->second.release()));
m_protocolHandlers.clear();
}
- jobFactory->SetProtocolHandler(url::kDataScheme, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::DataProtocolHandler()));
- jobFactory->SetProtocolHandler(url::kFileScheme, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::FileProtocolHandler(
+ jobFactory->SetProtocolHandler(url::kDataScheme, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::DataProtocolHandler()));
+ jobFactory->SetProtocolHandler(url::kFileScheme, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::FileProtocolHandler(
content::BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))));
- jobFactory->SetProtocolHandler(kQrcSchemeQt, scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new QrcProtocolHandlerQt()));
+ jobFactory->SetProtocolHandler(kQrcSchemeQt, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new QrcProtocolHandlerQt()));
jobFactory->SetProtocolHandler(url::kFtpScheme,
- scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::FtpProtocolHandler(new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))));
+ std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::FtpProtocolHandler(new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))));
m_installedCustomSchemes = m_customUrlSchemes;
Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
- jobFactory->SetProtocolHandler(scheme.toStdString(), scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext)));
+ jobFactory->SetProtocolHandler(scheme.toStdString(), std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext)));
}
m_baseJobFactory = jobFactory.get();
// Set up interceptors in the reverse order.
- scoped_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory);
+ std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory);
for (content::URLRequestInterceptorScopedVector::reverse_iterator i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i)
- topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), make_scoped_ptr(*i)));
+ topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), std::unique_ptr<net::URLRequestInterceptor>(*i)));
m_requestInterceptors.weak_clear();
@@ -570,7 +579,7 @@ void URLRequestContextGetterQt::regenerateJobFactory()
m_installedCustomSchemes = m_customUrlSchemes;
Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
- m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext)));
+ m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContext)));
}
}
diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h
index dd51fd72c..8cfa8d759 100644
--- a/src/core/url_request_context_getter_qt.h
+++ b/src/core/url_request_context_getter_qt.h
@@ -44,8 +44,8 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/url_constants.h"
#include "net/http/http_network_session.h"
@@ -116,15 +116,15 @@ private:
content::ProtocolHandlerMap m_protocolHandlers;
QAtomicPointer<net::ProxyConfigService> m_proxyConfigService;
- scoped_ptr<net::URLRequestContext> m_urlRequestContext;
- scoped_ptr<NetworkDelegateQt> m_networkDelegate;
- scoped_ptr<net::URLRequestContextStorage> m_storage;
- scoped_ptr<net::URLRequestJobFactory> m_jobFactory;
+ std::unique_ptr<net::URLRequestContext> m_urlRequestContext;
+ std::unique_ptr<NetworkDelegateQt> m_networkDelegate;
+ std::unique_ptr<net::URLRequestContextStorage> m_storage;
+ std::unique_ptr<net::URLRequestJobFactory> m_jobFactory;
net::URLRequestJobFactoryImpl *m_baseJobFactory;
- scoped_ptr<net::DhcpProxyScriptFetcherFactory> m_dhcpProxyScriptFetcherFactory;
+ std::unique_ptr<net::DhcpProxyScriptFetcherFactory> m_dhcpProxyScriptFetcherFactory;
scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate;
content::URLRequestInterceptorScopedVector m_requestInterceptors;
- scoped_ptr<net::HttpNetworkSession> m_httpNetworkSession;
+ std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession;
QList<QByteArray> m_installedCustomSchemes;
QWebEngineUrlRequestInterceptor* m_requestInterceptor;
diff --git a/src/core/user_script.cpp b/src/core/user_script.cpp
index 839eff366..b33dd6a7d 100644
--- a/src/core/user_script.cpp
+++ b/src/core/user_script.cpp
@@ -38,11 +38,39 @@
****************************************************************************/
#include "common/user_script_data.h"
+#include "extensions/common/url_pattern.h"
#include "user_script.h"
#include "type_conversion.h"
+namespace {
+
+// Helper function to parse Greasemonkey headers
+bool GetDeclarationValue(const base::StringPiece& line,
+ const base::StringPiece& prefix,
+ std::string* value) {
+ base::StringPiece::size_type index = line.find(prefix);
+ if (index == base::StringPiece::npos)
+ return false;
+
+ std::string temp(line.data() + index + prefix.length(),
+ line.length() - index - prefix.length());
+
+ if (temp.empty() || !base::IsUnicodeWhitespace(temp[0]))
+ return false;
+
+ base::TrimWhitespaceASCII(temp, base::TRIM_ALL, value);
+ return true;
+}
+
+} // namespace
+
namespace QtWebEngineCore {
+int UserScript::validUserScriptSchemes()
+{
+ return URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS | URLPattern::SCHEME_FILE;
+}
+
ASSERT_ENUMS_MATCH(UserScript::AfterLoad, UserScriptData::AfterLoad)
ASSERT_ENUMS_MATCH(UserScript::DocumentLoadFinished, UserScriptData::DocumentLoadFinished)
ASSERT_ENUMS_MATCH(UserScript::DocumentElementCreation, UserScriptData::DocumentElementCreation)
@@ -100,6 +128,7 @@ void UserScript::setSourceCode(const QString &source)
{
initData();
scriptData->source = source.toStdString();
+ parseMetadataHeader();
}
UserScript::InjectionPoint UserScript::injectionPoint() const
@@ -169,4 +198,80 @@ UserScriptData &UserScript::data() const
return *(scriptData.data());
}
+void UserScript::parseMetadataHeader()
+{
+ // Logic taken from Chromium (extensions/browser/user_script_loader.cc)
+ // http://wiki.greasespot.net/Metadata_block
+ const std::string &script_text = scriptData->source;
+ base::StringPiece line;
+ size_t line_start = 0;
+ size_t line_end = line_start;
+ bool in_metadata = false;
+
+ static const base::StringPiece kUserScriptBegin("// ==UserScript==");
+ static const base::StringPiece kUserScriptEnd("// ==/UserScript==");
+ static const base::StringPiece kNameDeclaration("// @name");
+ static const base::StringPiece kIncludeDeclaration("// @include");
+ static const base::StringPiece kExcludeDeclaration("// @exclude");
+ static const base::StringPiece kMatchDeclaration("// @match");
+ static const base::StringPiece kRunAtDeclaration("// @run-at");
+ static const base::StringPiece kRunAtDocumentStartValue("document-start");
+ static const base::StringPiece kRunAtDocumentEndValue("document-end");
+ static const base::StringPiece kRunAtDocumentIdleValue("document-idle");
+ // FIXME: Scripts don't run in subframes by default. If we would like to
+ // support @noframes rule, we have to change the current default behavior.
+ // static const base::StringPiece kNoFramesDeclaration("// @noframes");
+
+ static URLPattern urlPatternParser(validUserScriptSchemes());
+
+ while (line_start < script_text.length()) {
+ line_end = script_text.find('\n', line_start);
+
+ // Handle the case where there is no trailing newline in the file.
+ if (line_end == std::string::npos)
+ line_end = script_text.length() - 1;
+
+ line.set(script_text.data() + line_start, line_end - line_start);
+
+ if (!in_metadata) {
+ if (line.starts_with(kUserScriptBegin))
+ in_metadata = true;
+ } else {
+ if (line.starts_with(kUserScriptEnd))
+ break;
+
+ std::string value;
+ if (GetDeclarationValue(line, kNameDeclaration, &value)) {
+ setName(toQt(value));
+ } else if (GetDeclarationValue(line, kIncludeDeclaration, &value)) {
+ // We escape some characters that MatchPattern() considers special.
+ base::ReplaceSubstringsAfterOffset(&value, 0, "\\", "\\\\");
+ base::ReplaceSubstringsAfterOffset(&value, 0, "?", "\\?");
+ scriptData->globs.push_back(value);
+ } else if (GetDeclarationValue(line, kExcludeDeclaration, &value)) {
+ base::ReplaceSubstringsAfterOffset(&value, 0, "\\", "\\\\");
+ base::ReplaceSubstringsAfterOffset(&value, 0, "?", "\\?");
+ scriptData->excludeGlobs.push_back(value);
+ } else if (GetDeclarationValue(line, kMatchDeclaration, &value)) {
+ if (URLPattern::PARSE_SUCCESS == urlPatternParser.Parse(value))
+ scriptData->urlPatterns.push_back(value);
+ } else if (GetDeclarationValue(line, kRunAtDeclaration, &value)) {
+ if (value == kRunAtDocumentStartValue)
+ scriptData->injectionPoint = DocumentElementCreation;
+ else if (value == kRunAtDocumentEndValue)
+ scriptData->injectionPoint = DocumentLoadFinished;
+ else if (value == kRunAtDocumentIdleValue)
+ scriptData->injectionPoint = AfterLoad;
+ }
+ }
+
+ line_start = line_end + 1;
+ }
+
+ // If no patterns were specified, default to @include *. This is what
+ // Greasemonkey does.
+ if (scriptData->globs.empty() && scriptData->urlPatterns.empty())
+ scriptData->globs.push_back("*");
+}
+
} // namespace QtWebEngineCore
diff --git a/src/core/user_script.h b/src/core/user_script.h
index 9d7d66a58..e44efd3e9 100644
--- a/src/core/user_script.h
+++ b/src/core/user_script.h
@@ -85,9 +85,12 @@ public:
bool operator==(const UserScript &) const;
+ static int validUserScriptSchemes();
+
private:
void initData();
UserScriptData &data() const;
+ void parseMetadataHeader();
friend class UserResourceControllerHost;
QScopedPointer<UserScriptData> scriptData;
diff --git a/src/core/web_channel_ipc_transport_host.h b/src/core/web_channel_ipc_transport_host.h
index 9cc1f3104..75b40477e 100644
--- a/src/core/web_channel_ipc_transport_host.h
+++ b/src/core/web_channel_ipc_transport_host.h
@@ -62,7 +62,7 @@ public:
virtual void RenderViewHostChanged(content::RenderViewHost* old_host, content::RenderViewHost* new_host) Q_DECL_OVERRIDE;
// QWebChannelAbstractTransport
- virtual void sendMessage(const QJsonObject &message) Q_DECL_OVERRIDE;
+ void sendMessage(const QJsonObject &message) Q_DECL_OVERRIDE;
void setWorldId(uint worldId);
uint worldId() const { return m_worldId; }
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index bfac6a5b2..6cbfe2867 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -46,9 +46,11 @@
#include "browser_accessibility_qt.h"
#include "browser_context_adapter.h"
+#include "browser_context_adapter_client.h"
#include "browser_context_qt.h"
#include "download_manager_delegate_qt.h"
#include "media_capture_devices_dispatcher.h"
+#include "pdfium_printing_wrapper_qt.h"
#include "print_view_manager_qt.h"
#include "qwebenginecallback_p.h"
#include "render_view_observer_host_qt.h"
@@ -90,6 +92,9 @@
#include <QtGui/qaccessible.h>
#include <QtGui/qdrag.h>
#include <QtGui/qpixmap.h>
+#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER)
+#include <QtPrintSupport/qprinter.h>
+#endif // QT_NO_PRINTER
#include <QtWebChannel/QWebChannel>
namespace QtWebEngineCore {
@@ -188,6 +193,17 @@ static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient,
}
}
+#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER)
+static void callbackOnPrintingOnPrinterFinished(WebContentsAdapterClient *adapterClient, int requestId, QPrinter *printer, const std::vector<char> &result)
+{
+ if (requestId) {
+ PdfiumPrintingWrapperQt printWrapper(result.data(), result.size());
+ bool printerResult = printWrapper.printOnPrinter(*printer);
+ adapterClient->didPrintPageOnPrinter(requestId, printerResult);
+ }
+}
+#endif // QT_NO_PRINTER
+
static content::WebContents *createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext)
{
content::WebContents::CreateParams create_params(browserContext, NULL);
@@ -231,7 +247,7 @@ static void serializeNavigationHistory(const content::NavigationController &cont
}
}
-static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, std::vector<scoped_ptr<content::NavigationEntry>> *entries, content::BrowserContext *browserContext)
+static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, std::vector<std::unique_ptr<content::NavigationEntry>> *entries, content::BrowserContext *browserContext)
{
int version;
input >> version;
@@ -280,7 +296,7 @@ static void deserializeNavigationHistory(QDataStream &input, int *currentIndex,
return;
}
- scoped_ptr<content::NavigationEntry> entry = content::NavigationController::CreateNavigationEntry(
+ std::unique_ptr<content::NavigationEntry> entry = content::NavigationController::CreateNavigationEntry(
toGurl(virtualUrl),
content::Referrer(toGurl(referrerUrl), static_cast<blink::WebReferrerPolicy>(referrerPolicy)),
// Use a transition type of reload so that we don't incorrectly
@@ -351,7 +367,7 @@ WebContentsAdapterPrivate::~WebContentsAdapterPrivate()
QSharedPointer<WebContentsAdapter> WebContentsAdapter::createFromSerializedNavigationHistory(QDataStream &input, WebContentsAdapterClient *adapterClient)
{
int currentIndex;
- std::vector<scoped_ptr<content::NavigationEntry>> entries;
+ std::vector<std::unique_ptr<content::NavigationEntry>> entries;
deserializeNavigationHistory(input, &currentIndex, &entries, adapterClient->browserContextAdapter()->browserContext());
if (currentIndex == -1)
@@ -469,21 +485,21 @@ void WebContentsAdapter::stop()
controller.RemoveEntryAtIndex(index);
d->webContents->Stop();
- d->webContents->Focus();
+ focusIfNecessary();
}
void WebContentsAdapter::reload()
{
Q_D(WebContentsAdapter);
d->webContents->GetController().Reload(/*checkRepost = */false);
- d->webContents->Focus();
+ focusIfNecessary();
}
void WebContentsAdapter::reloadAndBypassCache()
{
Q_D(WebContentsAdapter);
- d->webContents->GetController().ReloadIgnoringCache(/*checkRepost = */false);
- d->webContents->Focus();
+ d->webContents->GetController().ReloadBypassingCache(/*checkRepost = */false);
+ focusIfNecessary();
}
void WebContentsAdapter::load(const QUrl &url)
@@ -502,11 +518,23 @@ void WebContentsAdapter::load(const QUrl &url)
Q_UNUSED(guard);
Q_D(WebContentsAdapter);
- content::NavigationController::LoadURLParams params(toGurl(url));
+ GURL gurl = toGurl(url);
+
+ // Add URL scheme if missing from view-source URL.
+ if (url.scheme() == content::kViewSourceScheme) {
+ QUrl pageUrl = QUrl(url.toString().remove(0, strlen(content::kViewSourceScheme) + 1));
+ if (pageUrl.scheme().isEmpty()) {
+ QUrl extendedUrl = QUrl::fromUserInput(pageUrl.toString());
+ extendedUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, extendedUrl.toString()));
+ gurl = toGurl(extendedUrl);
+ }
+ }
+
+ content::NavigationController::LoadURLParams params(gurl);
params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
d->webContents->GetController().LoadURLWithParams(params);
- d->webContents->Focus();
+ focusIfNecessary();
}
void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
@@ -519,7 +547,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT
urlString.append(encodedData.constData(), encodedData.length());
GURL dataUrlToLoad(urlString);
- if (dataUrlToLoad.spec().size() > content::kMaxURLChars) {
+ if (dataUrlToLoad.spec().size() > url::kMaxURLChars) {
d->adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED);
return;
}
@@ -531,13 +559,14 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT
params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_API);
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
d->webContents->GetController().LoadURLWithParams(params);
- d->webContents->Focus();
+ focusIfNecessary();
d->webContents->Unselect();
}
-void WebContentsAdapter::save()
+void WebContentsAdapter::save(const QString &filePath, int savePageFormat)
{
Q_D(WebContentsAdapter);
+ d->webContentsDelegate->setSavePageInfo(SavePageInfo(filePath, savePageFormat));
d->webContents->OnSavePage();
}
@@ -631,7 +660,7 @@ void WebContentsAdapter::selectAll()
void WebContentsAdapter::requestClose()
{
Q_D(WebContentsAdapter);
- d->webContents->DispatchBeforeUnload(false);
+ d->webContents->DispatchBeforeUnload();
}
void WebContentsAdapter::unselect()
@@ -644,14 +673,14 @@ void WebContentsAdapter::navigateToIndex(int offset)
{
Q_D(WebContentsAdapter);
d->webContents->GetController().GoToIndex(offset);
- d->webContents->Focus();
+ focusIfNecessary();
}
void WebContentsAdapter::navigateToOffset(int offset)
{
Q_D(WebContentsAdapter);
d->webContents->GetController().GoToOffset(offset);
- d->webContents->Focus();
+ focusIfNecessary();
}
int WebContentsAdapter::navigationEntryCount()
@@ -849,13 +878,19 @@ void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & we
void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileName)
{
+ Q_D(WebContentsAdapter);
content::BrowserContext *bctx = webContents()->GetBrowserContext();
content::DownloadManager *dlm = content::BrowserContext::GetDownloadManager(bctx);
+ DownloadManagerDelegateQt *dlmd = d->browserContextAdapter->downloadManagerDelegate();
+
if (!dlm)
return;
- scoped_ptr<content::DownloadUrlParameters> params(
- content::DownloadUrlParameters::FromWebContents(webContents(), toGurl(url)));
+ dlmd->setDownloadType(BrowserContextAdapterClient::UserRequested);
+ dlm->SetDelegate(dlmd);
+
+ std::unique_ptr<content::DownloadUrlParameters> params(
+ content::DownloadUrlParameters::CreateForWebContentsMainFrame(webContents(), toGurl(url)));
params->set_suggested_name(toString16(suggestedFileName));
dlm->DownloadUrl(std::move(params));
}
@@ -881,7 +916,7 @@ bool WebContentsAdapter::recentlyAudible()
void WebContentsAdapter::copyImageAt(const QPoint &location)
{
Q_D(WebContentsAdapter);
- d->webContents->GetRenderViewHost()->CopyImageAt(location.x(), location.y());
+ d->webContents->GetRenderViewHost()->GetMainFrame()->CopyImageAt(location.x(), location.y());
}
ASSERT_ENUMS_MATCH(WebContentsAdapter::MediaPlayerNoAction, blink::WebMediaPlayerAction::Unknown)
@@ -916,13 +951,13 @@ bool WebContentsAdapter::hasInspector() const
void WebContentsAdapter::exitFullScreen()
{
Q_D(WebContentsAdapter);
- d->webContents->ExitFullscreen();
+ d->webContents->ExitFullscreen(false);
}
void WebContentsAdapter::changedFullScreen()
{
Q_D(WebContentsAdapter);
- d->webContents->NotifyFullscreenChanged();
+ d->webContents->NotifyFullscreenChanged(false);
}
void WebContentsAdapter::wasShown()
@@ -940,7 +975,7 @@ void WebContentsAdapter::wasHidden()
void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString &filePath)
{
#if defined(ENABLE_BASIC_PRINTING)
- PrintViewManagerQt::FromWebContents(webContents())->PrintToPDF(pageLayout, filePath);
+ PrintViewManagerQt::FromWebContents(webContents())->PrintToPDF(pageLayout, true, filePath);
#endif // if defined(ENABLE_BASIC_PRINTING)
}
@@ -948,13 +983,33 @@ quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayo
{
#if defined(ENABLE_BASIC_PRINTING)
Q_D(WebContentsAdapter);
- PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished, d->adapterClient, d->nextRequestId);
- PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, callback);
+ PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished
+ , d->adapterClient
+ , d->nextRequestId);
+ PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(pageLayout, true
+ , callback);
+ return d->nextRequestId++;
+#else
+ return 0;
+#endif // if defined(ENABLE_BASIC_PRINTING)
+}
+
+#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER)
+quint64 WebContentsAdapter::printOnPrinterCallbackResult(QPrinter *printer)
+{
+#if defined(ENABLE_BASIC_PRINTING)
+ Q_D(WebContentsAdapter);
+ PrintViewManagerQt::PrintToPDFCallback callback
+ = base::Bind(&callbackOnPrintingOnPrinterFinished, d->adapterClient
+ , d->nextRequestId, printer);
+ PrintViewManagerQt::FromWebContents(webContents())->PrintToPDFWithCallback(
+ printer->pageLayout(), printer->colorMode() == QPrinter::Color, callback);
return d->nextRequestId++;
#else
return 0;
#endif // if defined(ENABLE_BASIC_PRINTING)
}
+#endif // QT_NO_PRINTER
QPointF WebContentsAdapter::lastScrollOffset() const
{
@@ -1143,7 +1198,7 @@ void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPoint &screenPos)
{
Q_D(WebContentsAdapter);
- scoped_ptr<content::DropData> ownedDropData;
+ std::unique_ptr<content::DropData> ownedDropData;
const content::DropData *rvhDropData = d->currentDropData;
if (!rvhDropData) {
// The drag originated outside the WebEngineView.
@@ -1199,7 +1254,7 @@ void WebContentsAdapter::endDragging(const QPoint &clientPos, const QPoint &scre
Q_D(WebContentsAdapter);
finishDragUpdate();
content::RenderViewHost *rvh = d->webContents->GetRenderViewHost();
- rvh->DragTargetDrop(toGfx(clientPos), toGfx(screenPos), 0);
+ rvh->DragTargetDrop(*d->currentDropData, toGfx(clientPos), toGfx(screenPos), 0);
}
void WebContentsAdapter::leaveDrag()
@@ -1238,6 +1293,15 @@ void WebContentsAdapter::replaceMisspelling(const QString &word)
#endif
}
+void WebContentsAdapter::focusIfNecessary()
+{
+ Q_D(WebContentsAdapter);
+ const WebEngineSettings *settings = d->adapterClient->webEngineSettings();
+ bool focusOnNavigation = settings->testAttribute(WebEngineSettings::FocusOnNavigationEnabled);
+ if (focusOnNavigation)
+ d->webContents->Focus();
+}
+
WebContentsAdapterClient::RenderProcessTerminationStatus
WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) {
auto status = WebContentsAdapterClient::RenderProcessTerminationStatus(-1);
@@ -1276,4 +1340,16 @@ FaviconManager *WebContentsAdapter::faviconManager()
return d->webContentsDelegate->faviconManager();
}
+void WebContentsAdapter::viewSource()
+{
+ Q_D(WebContentsAdapter);
+ d->webContents->ViewSource();
+}
+
+bool WebContentsAdapter::canViewSource()
+{
+ Q_D(WebContentsAdapter);
+ return d->webContents->GetController().CanViewSource();
+}
+
} // namespace QtWebEngineCore
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index ec8cd7914..7a109770e 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -58,6 +58,9 @@ class QAccessibleInterface;
class QDragEnterEvent;
class QDragMoveEvent;
class QPageLayout;
+#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER)
+class QPrinter;
+#endif // QT_NO_PRINTER
class QString;
class QWebChannel;
QT_END_NAMESPACE
@@ -85,7 +88,7 @@ public:
void reloadAndBypassCache();
void load(const QUrl&);
void setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl);
- void save();
+ void save(const QString &filePath = QString(), int savePageFormat = -1);
QUrl activeUrl() const;
QUrl requestedUrl() const;
QString pageTitle() const;
@@ -174,10 +177,19 @@ public:
void printToPDF(const QPageLayout&, const QString&);
quint64 printToPDFCallbackResult(const QPageLayout &);
+#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER)
+ quint64 printOnPrinterCallbackResult(QPrinter *printer);
+#endif
+
// meant to be used within WebEngineCore only
content::WebContents *webContents() const;
void replaceMisspelling(const QString &word);
+ void viewSource();
+ bool canViewSource();
+ void focusIfNecessary();
+
+
private:
Q_DISABLE_COPY(WebContentsAdapter)
Q_DECLARE_PRIVATE(WebContentsAdapter)
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 3952067a7..85a379409 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -71,23 +71,43 @@ class WebContentsAdapter;
class WebContentsDelegateQt;
class WebEngineSettings;
-// FIXME: make this ref-counted and implicitely shared and expose as public API maybe ?
-class WebEngineContextMenuData {
+
+class WebEngineContextMenuSharedData : public QSharedData {
public:
- WebEngineContextMenuData()
- : mediaType(MediaTypeNone)
- , hasImageContent(false)
- , mediaFlags(0)
+ WebEngineContextMenuSharedData()
+ : hasImageContent(false)
, isEditable(false)
, isSpellCheckerEnabled(false)
+ , mediaType(0)
+ , mediaFlags(0)
{
}
+ bool hasImageContent;
+ bool isEditable;
+ bool isSpellCheckerEnabled;
+ uint mediaType;
+ uint mediaFlags;
+ QPoint pos;
+ QUrl linkUrl;
+ QUrl mediaUrl;
+ QString linkText;
+ QString selectedText;
+ QString suggestedFileName;
+ QString misspelledWord;
+ QStringList spellCheckerSuggestions;
+ // Some likely candidates for future additions as we add support for the related actions:
+ // bool isImageBlocked;
+ // <enum tbd> mediaType;
+ // ...
+};
+class WebEngineContextMenuData {
+public:
// Must match blink::WebContextMenuData::MediaType:
enum MediaType {
// No special node is in context.
- MediaTypeNone,
+ MediaTypeNone = 0x0,
// An image node is selected.
MediaTypeImage,
// A video node is selected.
@@ -117,25 +137,118 @@ public:
MediaCanRotate = 0x200,
};
- QPoint pos;
- QUrl linkUrl;
- QString linkText;
- QString selectedText;
- QUrl mediaUrl;
- MediaType mediaType;
- bool hasImageContent;
- uint mediaFlags;
- QString suggestedFileName;
- bool isEditable;
- bool isSpellCheckerEnabled;
- QString misspelledWord;
- QStringList spellCheckerSuggestions;
-// Some likely candidates for future additions as we add support for the related actions:
-// bool isImageBlocked;
-// <enum tbd> mediaType;
-// ...
+ WebEngineContextMenuData():d(new WebEngineContextMenuSharedData) {
+ }
+
+ void setPosition(const QPoint &pos) {
+ d->pos = pos;
+ }
+
+ QPoint position() const {
+ return d->pos;
+ }
+
+ void setLinkUrl(const QUrl &url) {
+ d->linkUrl = url;
+ }
+
+ QUrl linkUrl() const {
+ return d->linkUrl;
+ }
+
+ void setLinkText(const QString &text) {
+ d->linkText = text;
+ }
+
+ QString linkText() const {
+ return d->linkText;
+ }
+
+ void setSelectedText(const QString &text) {
+ d->selectedText = text;
+ }
+
+ QString selectedText() const {
+ return d->selectedText;
+ }
+
+ void setMediaUrl(const QUrl &url) {
+ d->mediaUrl = url;
+ }
+
+ QUrl mediaUrl() const {
+ return d->mediaUrl;
+ }
+
+ void setMediaType(MediaType type) {
+ d->mediaType = type;
+ }
+
+ MediaType mediaType() const {
+ return MediaType(d->mediaType);
+ }
+
+ void setHasImageContent(bool imageContent) {
+ d->hasImageContent = imageContent;
+ }
+
+ bool hasImageContent() const {
+ return d->hasImageContent;
+ }
+
+ void setMediaFlags(MediaFlags flags) {
+ d->mediaFlags = flags;
+ }
+
+ MediaFlags mediaFlags() const {
+ return MediaFlags(d->mediaFlags);
+ }
+
+ void setSuggestedFileName(const QString &filename) {
+ d->suggestedFileName = filename;
+ }
+
+ QString suggestedFileName() const {
+ return d->suggestedFileName;
+ }
+
+ void setIsEditable(bool editable) {
+ d->isEditable = editable;
+ }
+
+ bool isEditable() const {
+ return d->isEditable;
+ }
+
+ void setIsSpellCheckerEnabled(bool spellCheckerEnabled) {
+ d->isSpellCheckerEnabled = spellCheckerEnabled;
+ }
+
+ bool isSpellCheckerEnabled() const {
+ return d->isSpellCheckerEnabled;
+ }
+
+ void setMisspelledWord(const QString &word) {
+ d->misspelledWord = word;
+ }
+
+ QString misspelledWord() const {
+ return d->misspelledWord;
+ }
+
+ void setSpellCheckerSuggestions(const QStringList &suggestions) {
+ d->spellCheckerSuggestions = suggestions;
+ }
+
+ QStringList spellCheckerSuggestions() const {
+ return d->spellCheckerSuggestions;
+ }
+
+private:
+ QSharedDataPointer<WebEngineContextMenuSharedData> d;
};
+
class QWEBENGINE_EXPORT WebContentsAdapterClient {
public:
// This must match window_open_disposition_list.h.
@@ -227,13 +340,16 @@ public:
virtual void requestFullScreenMode(const QUrl &origin, bool fullscreen) = 0;
virtual bool isFullScreenMode() const = 0;
virtual void javascriptDialog(QSharedPointer<JavaScriptDialogController>) = 0;
- virtual void runFileChooser(FilePickerController *controller) = 0;
+ virtual void runFileChooser(QSharedPointer<FilePickerController>) = 0;
virtual void showColorDialog(QSharedPointer<ColorChooserController>) = 0;
virtual void didRunJavaScript(quint64 requestId, const QVariant& result) = 0;
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;
+#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER)
+ virtual void didPrintPageOnPrinter(quint64 requestId, bool result) = 0;
+#endif
virtual void passOnFocus(bool reverse) = 0;
// returns the last QObject (QWidget/QQuickItem) based object in the accessibility
// hierarchy before going into the BrowserAccessibility tree
@@ -259,6 +375,7 @@ public:
const QPixmap &pixmap, const QPoint &offset) = 0;
virtual bool isEnabled() const = 0;
virtual const QObject *holdingQObject() const = 0;
+ virtual void setToolTip(const QString& toolTipText) = 0;
virtual QSharedPointer<BrowserContextAdapter> browserContextAdapter() = 0;
virtual WebContentsAdapter* webContentsAdapter() = 0;
diff --git a/src/core/web_contents_adapter_p.h b/src/core/web_contents_adapter_p.h
index 5c0e83298..77522d299 100644
--- a/src/core/web_contents_adapter_p.h
+++ b/src/core/web_contents_adapter_p.h
@@ -55,7 +55,6 @@
#include <base/callback.h>
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include <QScopedPointer>
#include <QSharedPointer>
@@ -84,10 +83,10 @@ public:
~WebContentsAdapterPrivate();
scoped_refptr<WebEngineContext> engineContext;
QSharedPointer<BrowserContextAdapter> browserContextAdapter;
- scoped_ptr<content::WebContents> webContents;
- scoped_ptr<WebContentsDelegateQt> webContentsDelegate;
- scoped_ptr<RenderViewObserverHostQt> renderViewObserverHost;
- scoped_ptr<WebChannelIPCTransportHost> webChannelTransport;
+ std::unique_ptr<content::WebContents> webContents;
+ std::unique_ptr<WebContentsDelegateQt> webContentsDelegate;
+ std::unique_ptr<RenderViewObserverHostQt> renderViewObserverHost;
+ std::unique_ptr<WebChannelIPCTransportHost> webChannelTransport;
QWebChannel *webChannel;
unsigned int webChannelWorld;
WebContentsAdapterClient *adapterClient;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 3ade0d0f6..9d0965818 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -311,15 +311,16 @@ ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, content::FileChooserParam
ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, content::FileChooserParams::UploadFolder)
ASSERT_ENUMS_MATCH(FilePickerController::Save, content::FileChooserParams::Save)
-void WebContentsDelegateQt::RunFileChooser(content::WebContents *web_contents, const content::FileChooserParams &params)
+void WebContentsDelegateQt::RunFileChooser(content::RenderFrameHost *frameHost, const content::FileChooserParams &params)
{
QStringList acceptedMimeTypes;
acceptedMimeTypes.reserve(params.accept_types.size());
for (std::vector<base::string16>::const_iterator it = params.accept_types.begin(); it < params.accept_types.end(); ++it)
acceptedMimeTypes.append(toQt(*it));
- FilePickerController *controller = new FilePickerController(static_cast<FilePickerController::FileChooserMode>(params.mode), web_contents, toQt(params.default_file_name.value()), acceptedMimeTypes);
- m_viewClient->runFileChooser(controller);
+ m_filePickerController.reset(new FilePickerController(static_cast<FilePickerController::FileChooserMode>(params.mode),
+ web_contents(), toQt(params.default_file_name.value()), acceptedMimeTypes));
+ m_viewClient->runFileChooser(m_filePickerController);
}
bool WebContentsDelegateQt::AddMessageToConsole(content::WebContents *source, int32_t level, const base::string16 &message, int32_t line_no, const base::string16 &source_id)
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index d523aa16b..dad1e50f1 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -42,7 +42,6 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/permission_status.mojom.h"
#include "third_party/skia/include/core/SkColor.h"
#include "base/callback.h"
@@ -70,6 +69,23 @@ namespace QtWebEngineCore {
class WebContentsAdapterClient;
+class SavePageInfo
+{
+public:
+ SavePageInfo()
+ : requestedFormat(-1)
+ {
+ }
+
+ SavePageInfo(const QString &filePath, int format)
+ : requestedFilePath(filePath), requestedFormat(format)
+ {
+ }
+
+ QString requestedFilePath;
+ int requestedFormat;
+};
+
class WebContentsDelegateQt : public content::WebContentsDelegate
, public content::WebContentsObserver
{
@@ -92,7 +108,7 @@ public:
virtual void EnterFullscreenModeForTab(content::WebContents* web_contents, const GURL& origin) Q_DECL_OVERRIDE;
virtual void ExitFullscreenModeForTab(content::WebContents*) Q_DECL_OVERRIDE;
virtual bool IsFullscreenForTabOrPending(const content::WebContents* web_contents) const Q_DECL_OVERRIDE;
- virtual void RunFileChooser(content::WebContents *, const content::FileChooserParams &params) Q_DECL_OVERRIDE;
+ virtual void RunFileChooser(content::RenderFrameHost* render_frame_host, const content::FileChooserParams& params) Q_DECL_OVERRIDE;
virtual bool AddMessageToConsole(content::WebContents* source, int32_t level, const base::string16& message, int32_t line_no, const base::string16& source_id) Q_DECL_OVERRIDE;
virtual void FindReply(content::WebContents *source, int request_id, int number_of_matches, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update) Q_DECL_OVERRIDE;
virtual void RequestMediaAccessPermission(content::WebContents* web_contents, const content::MediaStreamRequest& request, const content::MediaResponseCallback& callback) Q_DECL_OVERRIDE;
@@ -126,6 +142,9 @@ public:
void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame);
FaviconManager *faviconManager();
+ void setSavePageInfo(const SavePageInfo &spi) { m_savePageInfo = spi; }
+ const SavePageInfo &savePageInfo() { return m_savePageInfo; }
+
private:
QWeakPointer<WebContentsAdapter> createWindow(content::WebContents *new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture);
@@ -134,6 +153,8 @@ private:
int m_lastReceivedFindReply;
QVector<int64_t> m_loadingErrorFrameList;
QScopedPointer<FaviconManager> m_faviconManager;
+ SavePageInfo m_savePageInfo;
+ QSharedPointer<FilePickerController> m_filePickerController;
};
} // namespace QtWebEngineCore
diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp
index e487fca46..ed6fdabff 100644
--- a/src/core/web_contents_view_qt.cpp
+++ b/src/core/web_contents_view_qt.cpp
@@ -155,19 +155,19 @@ ASSERT_ENUMS_MATCH(WebEngineContextMenuData::MediaCanRotate, blink::WebContextMe
static inline WebEngineContextMenuData fromParams(const content::ContextMenuParams &params)
{
WebEngineContextMenuData ret;
- ret.pos = QPoint(params.x, params.y);
- ret.linkUrl = toQt(params.link_url);
- ret.linkText = toQt(params.link_text.data());
- ret.selectedText = toQt(params.selection_text.data());
- ret.mediaUrl = toQt(params.src_url);
- ret.mediaType = (WebEngineContextMenuData::MediaType)params.media_type;
- ret.hasImageContent = params.has_image_contents;
- ret.mediaFlags = params.media_flags;
- ret.suggestedFileName = toQt(params.suggested_filename.data());
- ret.isEditable = params.is_editable;
+ ret.setPosition(QPoint(params.x, params.y));
+ ret.setLinkUrl(toQt(params.link_url));
+ ret.setLinkText(toQt(params.link_text.data()));
+ ret.setSelectedText(toQt(params.selection_text.data()));
+ ret.setMediaUrl(toQt(params.src_url));
+ ret.setMediaType((WebEngineContextMenuData::MediaType)params.media_type);
+ ret.setHasImageContent(params.has_image_contents);
+ ret.setMediaFlags((WebEngineContextMenuData::MediaFlags)params.media_flags);
+ ret.setSuggestedFileName(toQt(params.suggested_filename.data()));
+ ret.setIsEditable(params.is_editable);
#if defined(ENABLE_SPELLCHECK)
- ret.misspelledWord = toQt(params.misspelled_word);
- ret.spellCheckerSuggestions = fromVector(params.dictionary_suggestions);
+ ret.setMisspelledWord(toQt(params.misspelled_word));
+ ret.setSpellCheckerSuggestions(fromVector(params.dictionary_suggestions));
#endif
return ret;
}
@@ -183,7 +183,7 @@ void WebContentsViewQt::ShowContextMenu(content::RenderFrameHost *, const conten
// must be initialized to true due to the way how the initialization sequence
// in SpellCheck works ie. typing the first word triggers the creation
// of the SpellcheckService. Use user preference store instead.
- contextMenuData.isSpellCheckerEnabled = m_client->browserContextAdapter()->isSpellCheckEnabled();
+ contextMenuData.setIsSpellCheckerEnabled(m_client->browserContextAdapter()->isSpellCheckEnabled());
#endif
m_client->contextMenuRequested(contextMenuData);
}
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index 7d1e5d609..368ad48e2 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -51,6 +51,7 @@
#if defined(ENABLE_BASIC_PRINTING)
#include "chrome/browser/printing/print_job_manager.h"
#endif // defined(ENABLE_BASIC_PRINTING)
+#include "components/devtools_http_handler/devtools_http_handler.h"
#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/utility_process_host_impl.h"
@@ -150,10 +151,14 @@ bool usingQtQuick2DRenderer()
}
if (device.isEmpty())
+ device = QString::fromLocal8Bit(qgetenv("QT_QUICK_BACKEND"));
+ if (device.isEmpty())
device = QString::fromLocal8Bit(qgetenv("QMLSCENE_DEVICE"));
+ if (device.isEmpty())
+ device = QLatin1String("default");
- // This assumes that the plugin is installed and is going to be used by QtQuick.
- return device == QLatin1String("softwarecontext");
+ // Anything other than the default OpenGL device will need to render in 2D mode.
+ return device != QLatin1String("default");
}
#if defined(ENABLE_PLUGINS)
@@ -294,6 +299,9 @@ WebEngineContext::WebEngineContext()
parsedCommandLine->AppendSwitch(switches::kDisableZeroCopy);
parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferCompositorResources);
+ // Enabled on OS X and Linux but currently not working. It worked in 5.7 on OS X.
+ parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames);
+
if (useEmbeddedSwitches) {
// Inspired by the Android port's default switches
parsedCommandLine->AppendSwitch(switches::kEnableOverlayScrollbar);
@@ -314,7 +322,7 @@ WebEngineContext::WebEngineContext()
if (qt_gl_global_share_context()) {
if (!strcmp(qt_gl_global_share_context()->nativeHandle().typeName(), "QEGLNativeContext")) {
if (qt_gl_global_share_context()->isOpenGLES()) {
- glType = gfx::kGLImplementationEGLName;
+ glType = gl::kGLImplementationEGLName;
} else {
QOpenGLContext context;
QSurfaceFormat format;
@@ -332,7 +340,7 @@ WebEngineContext::WebEngineContext()
if (context.makeCurrent(&surface)) {
if (context.hasExtension("GL_ARB_ES2_compatibility"))
- glType = gfx::kGLImplementationEGLName;
+ glType = gl::kGLImplementationEGLName;
context.doneCurrent();
}
@@ -342,17 +350,17 @@ WebEngineContext::WebEngineContext()
}
} else {
if (!qt_gl_global_share_context()->isOpenGLES())
- glType = gfx::kGLImplementationDesktopName;
+ glType = gl::kGLImplementationDesktopName;
}
} else {
qWarning("WebEngineContext used before QtWebEngine::initialize()");
// We have to assume the default OpenGL module type will be used.
switch (QOpenGLContext::openGLModuleType()) {
case QOpenGLContext::LibGL:
- glType = gfx::kGLImplementationDesktopName;
+ glType = gl::kGLImplementationDesktopName;
break;
case QOpenGLContext::LibGLES:
- glType = gfx::kGLImplementationEGLName;
+ glType = gl::kGLImplementationEGLName;
break;
}
}
@@ -387,6 +395,8 @@ WebEngineContext::WebEngineContext()
// first gets referenced on the IO thread.
MediaCaptureDevicesDispatcher::GetInstance();
+ base::ThreadRestrictions::SetIOAllowed(true);
+
#if defined(ENABLE_PLUGINS)
// Creating pepper plugins from the page (which calls PluginService::GetPluginInfoArray)
// might fail unless the page queried the list of available plugins at least once
diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h
index 960f8ed47..878b651de 100644
--- a/src/core/web_engine_context.h
+++ b/src/core/web_engine_context.h
@@ -43,9 +43,7 @@
#include "qtwebenginecoreglobal.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/values.h"
-#include "components/devtools_http_handler/devtools_http_handler.h"
#include <QSharedPointer>
@@ -58,6 +56,10 @@ class BrowserMainRunner;
class ContentMainRunner;
}
+namespace devtools_http_handler {
+class DevToolsHttpHandler;
+}
+
#if defined(ENABLE_BASIC_PRINTING)
namespace printing {
class PrintJobManager;
@@ -89,15 +91,15 @@ private:
WebEngineContext();
~WebEngineContext();
- scoped_ptr<base::RunLoop> m_runLoop;
- scoped_ptr<ContentMainDelegateQt> m_mainDelegate;
- scoped_ptr<content::ContentMainRunner> m_contentRunner;
- scoped_ptr<content::BrowserMainRunner> m_browserRunner;
+ std::unique_ptr<base::RunLoop> m_runLoop;
+ std::unique_ptr<ContentMainDelegateQt> m_mainDelegate;
+ std::unique_ptr<content::ContentMainRunner> m_contentRunner;
+ std::unique_ptr<content::BrowserMainRunner> m_browserRunner;
QObject* m_globalQObject;
QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_defaultBrowserContext;
- scoped_ptr<devtools_http_handler::DevToolsHttpHandler> m_devtools;
+ std::unique_ptr<devtools_http_handler::DevToolsHttpHandler> m_devtools;
#if defined(ENABLE_BASIC_PRINTING)
- scoped_ptr<printing::PrintJobManager> m_printJobManager;
+ std::unique_ptr<printing::PrintJobManager> m_printJobManager;
#endif // defined(ENABLE_BASIC_PRINTING)
};
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index 399e36765..2be59d1c6 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -303,8 +303,16 @@ base::string16 WebEngineLibraryInfo::getApplicationName()
std::string WebEngineLibraryInfo::getApplicationLocale()
{
base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess();
- if (!parsedCommandLine->HasSwitch(switches::kLang))
- return QLocale().bcp47Name().toStdString();
+ if (!parsedCommandLine->HasSwitch(switches::kLang)) {
+ const QString &locale = QLocale().bcp47Name();
+
+ // QLocale::bcp47Name returns "en" for American English locale. Chromium requires the "US" suffix
+ // to clarify the dialect and ignores the shorter version.
+ if (locale == "en")
+ return "en-US";
+
+ return locale.toStdString();
+ }
return parsedCommandLine->GetSwitchValueASCII(switches::kLang);
}
diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp
index 550fd2814..8e284c9d6 100644
--- a/src/core/web_engine_settings.cpp
+++ b/src/core/web_engine_settings.cpp
@@ -239,6 +239,8 @@ void WebEngineSettings::initDefaults(bool offTheRecord)
s_defaultAttributes.insert(Accelerated2dCanvasEnabled, accelerated2dCanvas);
s_defaultAttributes.insert(AutoLoadIconsForPage, true);
s_defaultAttributes.insert(TouchIconsEnabled, false);
+ s_defaultAttributes.insert(FocusOnNavigationEnabled, true);
+ s_defaultAttributes.insert(PrintElementBackgrounds, true);
s_defaultAttributes.insert(AllowRunningInsecureContent, allowRunningInsecureContent);
}
if (offTheRecord)
@@ -315,6 +317,7 @@ void WebEngineSettings::applySettingsToWebPreferences(content::WebPreferences *p
prefs->fullscreen_supported = testAttribute(FullScreenSupportEnabled);
prefs->accelerated_2d_canvas_enabled = testAttribute(Accelerated2dCanvasEnabled);
prefs->experimental_webgl_enabled = testAttribute(WebGLEnabled);
+ prefs->should_print_backgrounds = testAttribute(PrintElementBackgrounds);
prefs->allow_running_insecure_content = testAttribute(AllowRunningInsecureContent);
// Fonts settings.
diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h
index e131af50c..8459ba75b 100644
--- a/src/core/web_engine_settings.h
+++ b/src/core/web_engine_settings.h
@@ -80,6 +80,8 @@ public:
Accelerated2dCanvasEnabled,
AutoLoadIconsForPage,
TouchIconsEnabled,
+ FocusOnNavigationEnabled,
+ PrintElementBackgrounds,
AllowRunningInsecureContent
};
diff --git a/src/core/web_engine_visited_links_manager.cpp b/src/core/web_engine_visited_links_manager.cpp
index ded9d5d24..0cf76d456 100644
--- a/src/core/web_engine_visited_links_manager.cpp
+++ b/src/core/web_engine_visited_links_manager.cpp
@@ -44,7 +44,6 @@
#include "content_browser_client_qt.h"
#include "type_conversion.h"
-#include "base/memory/scoped_ptr.h"
#include "components/visitedlink/browser/visitedlink_delegate.h"
#include "components/visitedlink/browser/visitedlink_master.h"
diff --git a/src/core/yuv_video_node.cpp b/src/core/yuv_video_node.cpp
index f8290878b..16e52575d 100644
--- a/src/core/yuv_video_node.cpp
+++ b/src/core/yuv_video_node.cpp
@@ -283,8 +283,19 @@ void YUVVideoMaterialShader::updateState(const RenderState &state, QSGMaterial *
break;
}
- program()->setUniformValue(m_id_yuvMatrix, QMatrix3x3(yuv_to_rgb));
- program()->setUniformValue(m_id_yuvAdjust, QVector3D(yuv_adjust[0], yuv_adjust[1], yuv_adjust[2]));
+ float yuv_to_rgb_multiplied[9];
+ float yuv_adjust_with_offset[3];
+
+ for (int i = 0; i < 9; ++i)
+ yuv_to_rgb_multiplied[i] = yuv_to_rgb[i] * mat->m_resourceMultiplier;
+
+ for (int i = 0; i < 3; ++i)
+ yuv_adjust_with_offset[i] =
+ yuv_adjust[i] / mat->m_resourceMultiplier - mat->m_resourceOffset;
+
+
+ program()->setUniformValue(m_id_yuvMatrix, QMatrix3x3(yuv_to_rgb_multiplied));
+ program()->setUniformValue(m_id_yuvAdjust, QVector3D(yuv_adjust_with_offset[0], yuv_adjust_with_offset[1], yuv_adjust_with_offset[2]));
if (state.isOpacityDirty())
program()->setUniformValue(m_id_opacity, state.opacity());
@@ -312,7 +323,8 @@ void YUVAVideoMaterialShader::updateState(const RenderState &state, QSGMaterial
YUVVideoMaterial::YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture,
const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize,
- YUVVideoMaterial::ColorSpace colorspace)
+ YUVVideoMaterial::ColorSpace colorspace,
+ float rMul, float rOff)
: m_yTexture(yTexture)
, m_uTexture(uTexture)
, m_vTexture(vTexture)
@@ -321,6 +333,8 @@ YUVVideoMaterial::YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, Q
, m_yaTexSize(yaTexSize)
, m_uvTexSize(uvTexSize)
, m_colorSpace(colorspace)
+ , m_resourceMultiplier(rMul)
+ , m_resourceOffset(rOff)
{
}
@@ -341,8 +355,9 @@ int YUVVideoMaterial::compare(const QSGMaterial *other) const
YUVAVideoMaterial::YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture,
const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize,
- YUVVideoMaterial::ColorSpace colorspace)
- : YUVVideoMaterial(yTexture, uTexture, vTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace)
+ YUVVideoMaterial::ColorSpace colorspace,
+ float rMul, float rOff)
+ : YUVVideoMaterial(yTexture, uTexture, vTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace, rMul, rOff)
, m_aTexture(aTexture)
{
setFlag(Blending, aTexture);
@@ -363,15 +378,15 @@ int YUVAVideoMaterial::compare(const QSGMaterial *other) const
YUVVideoNode::YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture,
const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize,
- YUVVideoMaterial::ColorSpace colorspace)
+ YUVVideoMaterial::ColorSpace colorspace, float rMul, float rOff)
: m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
{
setGeometry(&m_geometry);
setFlag(QSGNode::OwnsMaterial);
if (aTexture)
- m_material = new YUVAVideoMaterial(yTexture, uTexture, vTexture, aTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace);
+ m_material = new YUVAVideoMaterial(yTexture, uTexture, vTexture, aTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace, rMul, rOff);
else
- m_material = new YUVVideoMaterial(yTexture, uTexture, vTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace);
+ m_material = new YUVVideoMaterial(yTexture, uTexture, vTexture, yaTexCoordRect, uvTexCoordRect, yaTexSize, uvTexSize, colorspace, rMul, rOff);
setMaterial(m_material);
}
diff --git a/src/core/yuv_video_node.h b/src/core/yuv_video_node.h
index cce204fd3..670ec62b6 100644
--- a/src/core/yuv_video_node.h
+++ b/src/core/yuv_video_node.h
@@ -60,7 +60,7 @@ public:
};
YUVVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture,
const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize,
- ColorSpace colorspace);
+ ColorSpace colorspace, float rMul, float rOff);
virtual QSGMaterialType *type() const Q_DECL_OVERRIDE
{
@@ -79,7 +79,8 @@ public:
QSizeF m_yaTexSize;
QSizeF m_uvTexSize;
ColorSpace m_colorSpace;
-
+ float m_resourceMultiplier;
+ float m_resourceOffset;
};
class YUVAVideoMaterial : public YUVVideoMaterial
@@ -87,7 +88,7 @@ class YUVAVideoMaterial : public YUVVideoMaterial
public:
YUVAVideoMaterial(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture,
const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize,
- ColorSpace colorspace);
+ ColorSpace colorspace, float rMul, float rOff);
virtual QSGMaterialType *type() const Q_DECL_OVERRIDE
{
@@ -106,7 +107,7 @@ class YUVVideoNode : public QSGGeometryNode
public:
YUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture, QSGTexture *aTexture,
const QRectF &yaTexCoordRect, const QRectF &uvTexCoordRect, const QSizeF &yaTexSize, const QSizeF &uvTexSize,
- YUVVideoMaterial::ColorSpace colorspace);
+ YUVVideoMaterial::ColorSpace colorspace, float rMul, float rOff);
void setRect(const QRectF &rect);
private:
diff --git a/src/process/process.pro b/src/process/process.pro
index cd60b1f91..5e2e734f4 100644
--- a/src/process/process.pro
+++ b/src/process/process.pro
@@ -16,9 +16,9 @@ win32 {
load(qt_app)
-contains(QT_CONFIG, build_all): CONFIG += build_all
+qtConfig(build_all): CONFIG += build_all
-contains(QT_CONFIG, qt_framework) {
+qtConfig(framework) {
# Deploy the QtWebEngineProcess app bundle into the QtWebEngineCore framework.
DESTDIR = $$MODULE_BASE_OUTDIR/lib/QtWebEngineCore.framework/Versions/5/Helpers
} else {
@@ -28,7 +28,7 @@ contains(QT_CONFIG, qt_framework) {
}
msvc: QMAKE_LFLAGS *= /LARGEADDRESSAWARE
-contains(QT_CONFIG, qt_framework) {
+qtConfig(framework) {
target.path = $$[QT_INSTALL_LIBS]/QtWebEngineCore.framework/Versions/5/Helpers
} else {
target.path = $$[QT_INSTALL_LIBEXECS]
diff --git a/src/src.pro b/src/src.pro
index 64c1703fe..00e8301be 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -34,8 +34,10 @@ isQMLTestSupportApiEnabled() {
# FIXME: We probably want a bit more control over config options to tweak what to build/ship or not.
# Another example of where this could be necessary is to make it easy to build proprietery codecs support.
-!contains(WEBENGINE_CONFIG, no_ui_delegates): SUBDIRS += webengine/ui
-
+!contains(WEBENGINE_CONFIG, no_ui_delegates) {
+ SUBDIRS += webengine/ui \
+ webengine/ui2
+}
qtHaveModule(widgets) {
SUBDIRS += webenginewidgets
plugins.depends = webenginewidgets
diff --git a/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro
index de125cc76..1781b843d 100644
--- a/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro
+++ b/src/tools/qwebengine_convert_dict/qwebengine_convert_dict.pro
@@ -10,6 +10,9 @@ OBJECTS =
# Fixme: -Werror=unused-parameter in core
QMAKE_CXXFLAGS_WARN_ON =
+# Disable MSVC2015 warning C4577 ('noexcept' used with no exception handling mode specified)
+win32: QMAKE_CXXFLAGS_WARN_ON = -wd4577
+
# Issue with some template compliation, smb smart should look at it
win32: DEFINES += NOMINMAX
diff --git a/src/webengine/api/qquickwebenginecertificateerror.cpp b/src/webengine/api/qquickwebenginecertificateerror.cpp
index 51a942abe..855e61817 100644
--- a/src/webengine/api/qquickwebenginecertificateerror.cpp
+++ b/src/webengine/api/qquickwebenginecertificateerror.cpp
@@ -93,7 +93,9 @@ QQuickWebEngineCertificateError::QQuickWebEngineCertificateError(const QSharedPo
QQuickWebEngineCertificateError::~QQuickWebEngineCertificateError()
{
- rejectCertificate();
+ Q_D(QQuickWebEngineCertificateError);
+ if (!d->answered)
+ rejectCertificate();
}
@@ -195,6 +197,9 @@ QUrl QQuickWebEngineCertificateError::url() const
\value WebEngineCertificateError.CertificateValidityTooLong
The certificate has a validity period that is too long.
(Added in 5.7)
+ \value WebEngineCertificateError.CertificateTransparencyRequired
+ Certificate Transparency was required for this connection, but the server
+ did not provide CT information that complied with the policy. (Added in 5.8)
*/
QQuickWebEngineCertificateError::Error QQuickWebEngineCertificateError::error() const
{
diff --git a/src/webengine/api/qquickwebenginecertificateerror_p.h b/src/webengine/api/qquickwebenginecertificateerror_p.h
index d04dc2c62..27b2efa14 100644
--- a/src/webengine/api/qquickwebenginecertificateerror_p.h
+++ b/src/webengine/api/qquickwebenginecertificateerror_p.h
@@ -84,6 +84,7 @@ public:
CertificateWeakKey = -211,
CertificateNameConstraintViolation = -212,
CertificateValidityTooLong = -213,
+ CertificateTransparencyRequired = -214,
};
Q_ENUM(Error)
diff --git a/src/webengine/api/qquickwebenginecontextmenudata.cpp b/src/webengine/api/qquickwebenginecontextmenudata.cpp
deleted file mode 100644
index 2cc6eaf4b..000000000
--- a/src/webengine/api/qquickwebenginecontextmenudata.cpp
+++ /dev/null
@@ -1,209 +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 "qquickwebenginecontextmenudata_p.h"
-
-#include "web_contents_adapter_client.h"
-
-QT_BEGIN_NAMESPACE
-
-ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeNone, QQuickWebEngineContextMenuData::MediaTypeNone)
-ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeImage, QQuickWebEngineContextMenuData::MediaTypeImage)
-ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeAudio, QQuickWebEngineContextMenuData::MediaTypeAudio)
-ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeVideo, QQuickWebEngineContextMenuData::MediaTypeVideo)
-ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeCanvas, QQuickWebEngineContextMenuData::MediaTypeCanvas)
-ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeFile, QQuickWebEngineContextMenuData::MediaTypeFile)
-ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypePlugin, QQuickWebEngineContextMenuData::MediaTypePlugin)
-
-/*!
- \qmltype WebEngineContextMenuData
- \instantiates QQuickWebEngineContextMenuData
- \inqmlmodule QtWebEngine
- \since QtWebEngine 1.3
- \brief Provides context data for populating or extending a context menu with actions.
-
-
- WebEngineContextMenuData is returned by WebEngineView::contextMenuData() after a context menu event,
- and contains information about where the context menu event took place. This is also in the context
- in which any context specific WebEngineView::WebAction will be performed.
-*/
-
-QQuickWebEngineContextMenuData::QQuickWebEngineContextMenuData() : d(nullptr)
-{
-}
-
-QQuickWebEngineContextMenuData::~QQuickWebEngineContextMenuData()
-{
- delete d;
-}
-
-/*!
- \qmlproperty bool WebEngineContextMenuData::isValid
-
- Is \c true if the context data is valid; otherwise \c false.
-*/
-bool QQuickWebEngineContextMenuData::isValid() const
-{
- return d;
-}
-
-/*!
- \qmlproperty point WebEngineContextMenuData::position
-
-
- Returns the position of the context, usually the mouse position where the context menu event was triggered.
-*/
-QPoint QQuickWebEngineContextMenuData::position() const
-{
- return d ? d->pos : QPoint();
-}
-
-/*!
- \qmlproperty string WebEngineContextMenuData::linkText
-
- Returns the text of a link if the context is a link.
-*/
-QString QQuickWebEngineContextMenuData::linkText() const
-{
- return d ? d->linkText : QString();
-}
-
-/*!
- \qmlproperty url WebEngineContextMenuData::linkUrl
-
- Returns the URL of a link if the context is a link.
-*/
-QUrl QQuickWebEngineContextMenuData::linkUrl() const
-{
- return d ? d->linkUrl : QUrl();
-}
-
-/*!
- \qmlproperty string WebEngineContextMenuData::selectedText
-
- Returns the selected text of the context.
-*/
-QString QQuickWebEngineContextMenuData::selectedText() const
-{
- return d ? d->selectedText : QString();
-}
-
-/*!
- \qmlproperty url WebEngineContextMenuData::mediaUrl
-
- If the context is a media element, returns the URL of that media.
-*/
-QUrl QQuickWebEngineContextMenuData::mediaUrl() const
-{
- return d ? d->mediaUrl : QUrl();
-}
-
-/*!
- \qmlproperty enumeration WebEngineContextMenuData::mediaType
-
- Returns the type of the media element or \c MediaTypeNone if the context is not a media element.
-
- \value WebEngineContextMenuData.MediaTypeNone
- The context is not a media element.
- \value WebEngineContextMenuData.MediaTypeImage
- The context is an image element
- \value WebEngineContextMenuData.MediaTypeVideo
- The context is a video element
- \value WebEngineContextMenuData.MediaTypeAudio
- The context is an audio element
- \value WebEngineContextMenuData.MediaTypeCanvas
- The context is a canvas element
- \value WebEngineContextMenuData.MediaTypeFile
- The context is a file
- \value WebEngineContextMenuData.MediaTypePlugin
- The context is a plugin
-*/
-
-QQuickWebEngineContextMenuData::MediaType QQuickWebEngineContextMenuData::mediaType() const
-{
- return d ? static_cast<QQuickWebEngineContextMenuData::MediaType>(d->mediaType) : MediaTypeNone;
-}
-
-/*!
- \qmlproperty bool WebEngineContextMenuData::isContentEditable
-
- Returns \c true if the content is editable by the user; otherwise returns \c false.
-*/
-bool QQuickWebEngineContextMenuData::isContentEditable() const
-{
- return d ? d->isEditable : false;
-}
-
-void QQuickWebEngineContextMenuData::update(const QtWebEngineCore::WebEngineContextMenuData &update)
-{
- const QQuickWebEngineContextMenuData old(d);
- d = new QtWebEngineCore::WebEngineContextMenuData(update);
-
- if (isValid() != old.isValid())
- Q_EMIT isValidChanged();
-
- if (position() != old.position())
- Q_EMIT positionChanged();
-
- if (selectedText() != old.selectedText())
- Q_EMIT selectedTextChanged();
-
- if (linkText() != old.linkText())
- Q_EMIT linkTextChanged();
-
- if (linkUrl() != old.linkUrl())
- Q_EMIT linkUrlChanged();
-
- if (mediaUrl() != old.mediaUrl())
- Q_EMIT mediaUrlChanged();
-
- if (mediaType() != old.mediaType())
- Q_EMIT mediaTypeChanged();
-
- if (isContentEditable() != old.isContentEditable())
- Q_EMIT isContentEditableChanged();
-}
-
-QQuickWebEngineContextMenuData::QQuickWebEngineContextMenuData(const QQuickWebEngineContextMenuDataPrivate *p, QObject *parent)
- : QObject(parent)
- , d(p)
-{
-}
-
-QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginecontextmenurequest.cpp b/src/webengine/api/qquickwebenginecontextmenurequest.cpp
new file mode 100644
index 000000000..5ad2b1501
--- /dev/null
+++ b/src/webengine/api/qquickwebenginecontextmenurequest.cpp
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** 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 "qquickwebenginecontextmenurequest_p.h"
+#include "web_contents_adapter_client.h"
+
+QT_BEGIN_NAMESPACE
+
+ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeNone,
+ QQuickWebEngineContextMenuRequest::MediaTypeNone)
+ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeImage,
+ QQuickWebEngineContextMenuRequest::MediaTypeImage)
+ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeAudio,
+ QQuickWebEngineContextMenuRequest::MediaTypeAudio)
+ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeVideo,
+ QQuickWebEngineContextMenuRequest::MediaTypeVideo)
+ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeCanvas,
+ QQuickWebEngineContextMenuRequest::MediaTypeCanvas)
+ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypeFile,
+ QQuickWebEngineContextMenuRequest::MediaTypeFile)
+ASSERT_ENUMS_MATCH(QtWebEngineCore::WebEngineContextMenuData::MediaTypePlugin,
+ QQuickWebEngineContextMenuRequest::MediaTypePlugin)
+
+/*!
+ \qmltype ContextMenuRequest
+ \instantiates QQuickWebEngineContextMenuRequest
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.4
+
+ \brief A request for showing a context menu.
+
+ A ContextMenuRequest is passed as an argument of the
+ WebEngineView::contextMenuRequested signal. It provides further
+ information about the context of the request. The position of the
+ request origin can be found via the \l x and \l y properties.
+
+ The \l accepted property of the request indicates whether the request
+ is handled by the user code or the default context menu should
+ be displayed.
+
+ The following code uses a custom menu to handle the request:
+
+ \code
+ WebEngineView {
+ id: view
+ // ...
+ onContextMenuRequested: {
+ request.accepted = true;
+ myMenu.x = request.x;
+ myMenu.y = request.y;
+ myMenu.trigger.connect(view.triggerWebAction);
+ myMenu.popup();
+ }
+ // ...
+ }
+ \endcode
+*/
+
+QQuickWebEngineContextMenuRequest::QQuickWebEngineContextMenuRequest(
+ const QtWebEngineCore::WebEngineContextMenuData &data, QObject *parent):
+ QObject(parent)
+ , m_data(new QtWebEngineCore::WebEngineContextMenuData(data))
+ , m_accepted(false)
+{
+}
+
+QQuickWebEngineContextMenuRequest::~QQuickWebEngineContextMenuRequest()
+{
+}
+
+/*!
+ \qmlproperty int ContextMenuRequest::x
+ \readonly
+
+ The x coordinate of the user action from where the context
+ menu request originates.
+*/
+
+int QQuickWebEngineContextMenuRequest::x() const
+{
+ return m_data->position().x();
+}
+
+/*!
+ \qmlproperty int ContextMenuRequest::y
+ \readonly
+
+ The y coordinate of the user action from where the context
+ menu request originates.
+*/
+
+int QQuickWebEngineContextMenuRequest::y() const
+{
+ return m_data->position().y();
+}
+
+/*!
+ \qmlproperty string ContextMenuRequest::selectedText
+ \readonly
+
+ The selected text the context menu was created for.
+*/
+
+QString QQuickWebEngineContextMenuRequest::selectedText() const
+{
+ return m_data->selectedText();
+}
+
+/*!
+ \qmlproperty string ContextMenuRequest::linkText
+ \readonly
+
+ The text of the link if the context menu was requested for a link.
+*/
+
+QString QQuickWebEngineContextMenuRequest::linkText() const
+{
+ return m_data->linkText();
+}
+
+/*!
+ \qmlproperty url ContextMenuRequest::linkUrl
+ \readonly
+
+ The URL of the link if the selected web page content is a link.
+*/
+
+QUrl QQuickWebEngineContextMenuRequest::linkUrl() const
+{
+ return m_data->linkUrl();
+}
+
+/*!
+ \qmlproperty url ContextMenuRequest::mediaUrl
+ \readonly
+
+ The URL of media if the selected web content is a media element.
+*/
+
+QUrl QQuickWebEngineContextMenuRequest::mediaUrl() const
+{
+ return m_data->mediaUrl();
+}
+
+/*!
+ \qmlproperty enumeration ContextMenuRequest::mediaType
+ \readonly
+
+ The type of the media element or \c MediaTypeNone if
+ the selected web page content is not a media element.
+
+ \value ContextMenuRequest.MediaTypeNone
+ Not a media.
+ \value ContextMenuRequest.MediaTypeImage
+ An image.
+ \value ContextMenuRequest.MediaTypeVideo
+ A video.
+ \value ContextMenuRequest.MediaTypeAudio
+ An audio element.
+ \value ContextMenuRequest.MediaTypeCanvas
+ A canvas.
+ \value ContextMenuRequest.MediaTypeFile
+ A file.
+ \value ContextMenuRequest.MediaTypePlugin
+ A plugin.
+*/
+
+QQuickWebEngineContextMenuRequest::MediaType QQuickWebEngineContextMenuRequest::mediaType() const
+{
+ return static_cast<QQuickWebEngineContextMenuRequest::MediaType>(m_data->mediaType());
+}
+
+/*!
+ \qmlproperty bool ContextMenuRequest::isContentEditable
+ \readonly
+
+ Indicates whether the selected web content is editable.
+*/
+
+bool QQuickWebEngineContextMenuRequest::isContentEditable() const
+{
+ return m_data->isEditable();
+}
+
+/*!
+ \qmlproperty string ContextMenuRequest::misspelledWord
+ \readonly
+
+ If the context is a word considered misspelled by the spell-checker,
+ returns the misspelled word.
+*/
+
+QString QQuickWebEngineContextMenuRequest::misspelledWord() const
+{
+ return m_data->misspelledWord();
+}
+
+/*!
+ \qmlproperty stringlist ContextMenuRequest::spellCheckerSuggestions
+ \readonly
+
+ If the context is a word considered misspelled by the spell-checker,
+ returns a list of suggested replacements.
+*/
+
+QStringList QQuickWebEngineContextMenuRequest::spellCheckerSuggestions() const
+{
+ return m_data->spellCheckerSuggestions();
+}
+
+/*!
+ \qmlproperty bool ContextMenuRequest::accepted
+
+ Indicates whether the context menu request has been
+ handled by the signal handler.
+
+ If the property is \c false after any signal handlers
+ for WebEngineView::contextMenuRequested have been executed,
+ a default context menu will be shown.
+ To prevent this, set \c{request.accepted} to \c true.
+
+ The default is \c false.
+
+ \note The default content of the context menu depends on the
+ web element for which the request was actually generated.
+*/
+
+bool QQuickWebEngineContextMenuRequest::isAccepted() const
+{
+ return m_accepted;
+}
+
+void QQuickWebEngineContextMenuRequest::setAccepted(bool accepted)
+{
+ m_accepted = accepted;
+}
+
+QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginecontextmenudata_p.h b/src/webengine/api/qquickwebenginecontextmenurequest_p.h
index aa081cbe6..3d2de14a2 100644
--- a/src/webengine/api/qquickwebenginecontextmenudata_p.h
+++ b/src/webengine/api/qquickwebenginecontextmenurequest_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QQUICKWEBENGINECONTEXTMENUDATA_P_H
-#define QQUICKWEBENGINECONTEXTMENUDATA_P_H
+#ifndef QQUICKWEBENGINECONTEXTMENUREQUEST_H
+#define QQUICKWEBENGINECONTEXTMENUREQUEST_H
//
// W A R N I N G
@@ -49,30 +49,21 @@
// version without notice, or even be removed.
//
// We mean it.
-//
#include <private/qtwebengineglobal_p.h>
+#include <QtCore/QScopedPointer>
#include <QtCore/QObject>
-#include <QtCore/QPoint>
-#include <QtCore/QString>
#include <QtCore/QUrl>
-#include <QtQuick/QQuickItem>
namespace QtWebEngineCore {
-class WebEngineContextMenuData;
+ class WebEngineContextMenuData;
}
QT_BEGIN_NAMESPACE
-class QQuickWebEngineView;
-class QQuickWebEngineViewPrivate;
-
-class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineContextMenuData : public QObject {
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineContextMenuRequest: public QObject {
Q_OBJECT
public:
- QQuickWebEngineContextMenuData();
- ~QQuickWebEngineContextMenuData();
-
enum MediaType {
MediaTypeNone,
MediaTypeImage,
@@ -84,49 +75,41 @@ public:
};
Q_ENUM(MediaType)
- Q_PROPERTY(bool isValid READ isValid NOTIFY isValidChanged)
- Q_PROPERTY(QPoint position READ position NOTIFY positionChanged)
- Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
- Q_PROPERTY(QString linkText READ linkText NOTIFY linkTextChanged)
- Q_PROPERTY(QUrl linkUrl READ linkUrl NOTIFY linkUrlChanged)
- Q_PROPERTY(QUrl mediaUrl READ mediaUrl NOTIFY mediaUrlChanged)
- Q_PROPERTY(MediaType mediaType READ mediaType NOTIFY mediaTypeChanged)
- Q_PROPERTY(bool isContentEditable READ isContentEditable NOTIFY isContentEditableChanged)
-
- bool isValid() const;
-
- QPoint position() const;
+ Q_PROPERTY(int x READ x CONSTANT FINAL)
+ Q_PROPERTY(int y READ y CONSTANT FINAL)
+ Q_PROPERTY(QString selectedText READ selectedText CONSTANT FINAL)
+ Q_PROPERTY(QString linkText READ linkText CONSTANT FINAL)
+ Q_PROPERTY(QUrl linkUrl READ linkUrl CONSTANT FINAL)
+ Q_PROPERTY(QUrl mediaUrl READ mediaUrl CONSTANT FINAL)
+ Q_PROPERTY(MediaType mediaType READ mediaType CONSTANT FINAL)
+ Q_PROPERTY(bool isContentEditable READ isContentEditable CONSTANT FINAL)
+ Q_PROPERTY(QString misspelledWord READ misspelledWord CONSTANT FINAL)
+ Q_PROPERTY(QStringList spellCheckerSuggestions READ spellCheckerSuggestions CONSTANT FINAL)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL)
+
+ ~QQuickWebEngineContextMenuRequest();
+ int x() const;
+ int y() const;
QString selectedText() const;
QString linkText() const;
QUrl linkUrl() const;
QUrl mediaUrl() const;
MediaType mediaType() const;
bool isContentEditable() const;
-
-Q_SIGNALS:
- void isValidChanged();
- void positionChanged();
- void selectedTextChanged();
- void linkTextChanged();
- void linkUrlChanged();
- void mediaUrlChanged();
- void mediaTypeChanged();
- void isContentEditableChanged();
+ QString misspelledWord() const;
+ QStringList spellCheckerSuggestions() const;
+ bool isAccepted() const;
+ void setAccepted(bool accepted);
private:
- void update(const QtWebEngineCore::WebEngineContextMenuData &update);
-
+ QQuickWebEngineContextMenuRequest(const QtWebEngineCore::WebEngineContextMenuData &data, QObject *parent = nullptr);
+ QScopedPointer<QtWebEngineCore::WebEngineContextMenuData> m_data;
+ bool m_accepted;
friend class QQuickWebEngineView;
friend class QQuickWebEngineViewPrivate;
- Q_DISABLE_COPY(QQuickWebEngineContextMenuData)
- typedef QtWebEngineCore::WebEngineContextMenuData QQuickWebEngineContextMenuDataPrivate;
- QQuickWebEngineContextMenuData(const QQuickWebEngineContextMenuDataPrivate *priv, QObject *parent = 0);
- QQuickWebEngineContextMenuData &operator=(const QQuickWebEngineContextMenuDataPrivate *priv);
- const QQuickWebEngineContextMenuDataPrivate *d;
+ Q_DISABLE_COPY(QQuickWebEngineContextMenuRequest)
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(const QQuickWebEngineContextMenuData);
-
-#endif // QQUICKWEBENGINECONTEXTMENUDATA_P_H
+#endif // QQUICKWEBENGINECONTEXTMENUREQUEST_H
diff --git a/src/webengine/api/qquickwebenginedialogrequests.cpp b/src/webengine/api/qquickwebenginedialogrequests.cpp
new file mode 100644
index 000000000..d8111e62b
--- /dev/null
+++ b/src/webengine/api/qquickwebenginedialogrequests.cpp
@@ -0,0 +1,856 @@
+/****************************************************************************
+**
+** 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 "qquickwebenginedialogrequests_p.h"
+#include "authentication_dialog_controller.h"
+#include "javascript_dialog_controller.h"
+#include "color_chooser_controller.h"
+#include "file_picker_controller.h"
+#include "web_contents_adapter_client.h"
+
+QT_BEGIN_NAMESPACE
+
+using namespace QtWebEngineCore;
+
+ASSERT_ENUMS_MATCH(WebContentsAdapterClient::AlertDialog,
+ QQuickWebEngineJavaScriptDialogRequest::DialogTypeAlert)
+ASSERT_ENUMS_MATCH(WebContentsAdapterClient::ConfirmDialog,
+ QQuickWebEngineJavaScriptDialogRequest::DialogTypeConfirm)
+ASSERT_ENUMS_MATCH(WebContentsAdapterClient::PromptDialog,
+ QQuickWebEngineJavaScriptDialogRequest::DialogTypePrompt)
+ASSERT_ENUMS_MATCH(WebContentsAdapterClient::UnloadDialog,
+ QQuickWebEngineJavaScriptDialogRequest::DialogTypeBeforeUnload)
+
+ASSERT_ENUMS_MATCH(FilePickerController::Open,
+ QQuickWebEngineFileDialogRequest::FileModeOpen)
+ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple,
+ QQuickWebEngineFileDialogRequest::FileModeOpenMultiple)
+ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder,
+ QQuickWebEngineFileDialogRequest::FileModeUploadFolder)
+ASSERT_ENUMS_MATCH(FilePickerController::Save,
+ QQuickWebEngineFileDialogRequest::FileModeSave)
+
+/*!
+ \qmltype AuthenticationDialogRequest
+ \instantiates QQuickWebEngineAuthenticationDialogRequest
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.4
+
+ \brief A request for providing authentication credentials required
+ by proxies or HTTP servers.
+
+ An AuthenticationDialogRequest is passed as an argument of the
+ WebEngineView::authenticationDialogRequested signal. It is generated
+ when basic HTTP or proxy authentication is required. The type
+ of authentication can be checked with the \l type property.
+
+ The \l accepted property of the request indicates whether the request
+ is handled by the user code or the default dialog should be displayed.
+ If you set the \l accepted property to \c true, make sure to call
+ either \l dialogAccept() or \l dialogReject() afterwards.
+
+ The following code uses a custom dialog to handle the request:
+ \code
+
+ WebEngineView {
+ // ...
+ onAuthenticationDialogRequested: function(request) {
+ request.accepted = true;
+ myDialog.request = request // keep the reference to the request
+ myDialog.accept.connect(request.dialogAccept);
+ myDialog.reject.connect(request.dialogReject);
+ myDialog.visible = true;
+ }
+ // ...
+ }
+
+ \endcode
+*/
+
+QQuickWebEngineAuthenticationDialogRequest::QQuickWebEngineAuthenticationDialogRequest(
+ QSharedPointer<AuthenticationDialogController> controller,
+ QObject *parent):
+ QObject(parent)
+ , m_controller(controller.toWeakRef())
+ , m_url(controller->url())
+ , m_realm(controller->realm())
+ , m_type(controller->isProxy() ? AuthenticationTypeProxy
+ : AuthenticationTypeHTTP)
+ , m_host(controller->host())
+ , m_accepted(false)
+{
+
+}
+
+QQuickWebEngineAuthenticationDialogRequest::~QQuickWebEngineAuthenticationDialogRequest()
+{
+}
+
+/*!
+ \qmlproperty url AuthenticationDialogRequest::url
+ \readonly
+
+ The URL of the HTTP request for which authentication was requested.
+ In case of proxy authentication, this is a request URL which is proxied
+ via host.
+
+ \sa proxyHost
+*/
+
+QUrl QQuickWebEngineAuthenticationDialogRequest::url() const
+{
+ return m_url;
+}
+
+/*!
+ \qmlproperty string AuthenticationDialogRequest::realm
+ \readonly
+
+ The HTTP authentication realm attribute value of the \c WWW-Authenticate
+ header. Empty if \l type is AuthenticationTypeProxy.
+*/
+
+QString QQuickWebEngineAuthenticationDialogRequest::realm() const
+{
+ return m_realm;
+}
+
+/*!
+ \qmlproperty string AuthenticationDialogRequest::proxyHost
+ \readonly
+
+ The hostname of the authentication proxy.
+ Empty if \l type is AuthenticationTypeHTTP.
+*/
+
+QString QQuickWebEngineAuthenticationDialogRequest::proxyHost() const
+{
+ return m_host;
+}
+
+/*!
+ \qmlproperty AuthenticationType AuthenticationDialogRequest::type
+ \readonly
+
+ The type of the authentication request.
+
+ \value AuthenticationTypeHTTP
+ HTTP authentication.
+ \value AuthenticationTypeProxy
+ Proxy authentication.
+*/
+
+QQuickWebEngineAuthenticationDialogRequest::AuthenticationType
+QQuickWebEngineAuthenticationDialogRequest::type() const
+{
+ return m_type;
+}
+
+/*!
+ \qmlproperty bool AuthenticationDialogRequest::accepted
+
+ Indicates whether the authentication dialog request has been
+ accepted by the signal handler.
+
+ If the property is \c false after any signal handlers
+ for WebEngineView::authenticationDialogRequested have been executed,
+ a default authentication dialog will be shown.
+ To prevent this, set \c{request.accepted} to \c true.
+
+ The default is \c false.
+*/
+
+bool QQuickWebEngineAuthenticationDialogRequest::isAccepted() const
+{
+ return m_accepted;
+}
+
+void QQuickWebEngineAuthenticationDialogRequest::setAccepted(bool accepted)
+{
+ m_accepted = accepted;
+}
+
+/*!
+ \qmlmethod void AuthenticationDialogRequest::dialogAccept(string username, string password)
+
+ This function notifies the engine that the user accepted the dialog,
+ providing the \a username and the \a password required for authentication.
+*/
+
+void QQuickWebEngineAuthenticationDialogRequest::dialogAccept(const QString &user,
+ const QString &password)
+{
+ m_accepted = true;
+ QSharedPointer<AuthenticationDialogController> controller
+ = m_controller.toStrongRef();
+ if (controller)
+ controller->accept(user,password);
+}
+
+/*!
+ \qmlmethod void AuthenticationDialogRequest::dialogReject()
+
+ This function notifies the engine that the user rejected the dialog and the
+ authentication shall not proceed.
+*/
+
+void QQuickWebEngineAuthenticationDialogRequest::dialogReject()
+{
+ m_accepted = true;
+ QSharedPointer<AuthenticationDialogController> controller
+ = m_controller.toStrongRef();
+ if (controller)
+ controller->reject();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \qmltype JavaScriptDialogRequest
+ \instantiates QQuickWebEngineJavaScriptDialogRequest
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.4
+
+ \brief A request for showing an alert, a confirmation, or a prompt dialog
+ from within JavaScript to the user.
+
+ A JavaScriptDialogRequest is passed as an argument of the
+ WebEngineView::javaScriptDialogRequested signal. The request is emitted
+ if JavaScript on the page calls HTML5's
+ \l{https://www.w3.org/TR/html5/webappapis.html#simple-dialogs}{Simple Dialogs}
+ API, or in response to HTML5's
+ \l {https://www.w3.org/TR/html5/browsers.html#beforeunloadevent}{BeforeUnloadEvent}.
+ The type of a particular dialog can be checked with the \l type property.
+
+ The \l accepted property of the request indicates whether the request
+ is handled by the user code or the default dialog should be displayed.
+ If you set the \l accepted property to \c true, make sure to call either
+ \l dialogAccept() or \l dialogReject() afterwards. The JavaScript call
+ causing the request will be blocked until then.
+
+ The following code uses a custom dialog to handle the request:
+
+ \code
+ WebEngineView {
+ // ...
+ onJavaScriptDialogRequested: function(request) {
+ request.accepted = true;
+ myDialog.request = request // keep the reference to the request
+ myDialog.accept.connect(request.dialogAccept);
+ myDialog.reject.connect(request.dialogReject);
+ myDialog.visible = true;
+ }
+ // ...
+ }
+ \endcode
+*/
+
+QQuickWebEngineJavaScriptDialogRequest::QQuickWebEngineJavaScriptDialogRequest(
+ QSharedPointer<JavaScriptDialogController> controller, QObject *parent):
+ QObject(parent)
+ , m_controller(controller.toWeakRef())
+ , m_message(controller->message())
+ , m_defaultPrompt(controller->defaultPrompt())
+ , m_title(controller->title())
+ , m_type(static_cast<QQuickWebEngineJavaScriptDialogRequest::DialogType>(controller->type()))
+ , m_securityOrigin(controller->securityOrigin())
+ , m_accepted(false)
+{
+}
+
+QQuickWebEngineJavaScriptDialogRequest::~QQuickWebEngineJavaScriptDialogRequest()
+{
+
+}
+
+/*!
+ \qmlproperty string JavaScriptDialogRequest::message
+ \readonly
+
+ The message to be shown to the user.
+*/
+
+QString QQuickWebEngineJavaScriptDialogRequest::message() const
+{
+ return m_message;
+}
+
+/*!
+ \qmlproperty string JavaScriptDialogRequest::defaultPrompt
+ \readonly
+
+ The default text if the requested dialog box is of
+ the \l type PromptDialog.
+*/
+
+
+QString QQuickWebEngineJavaScriptDialogRequest::defaultText() const
+{
+ return m_defaultPrompt;
+}
+
+/*!
+ \qmlproperty string JavaScriptDialogRequest::title
+ \readonly
+
+ A default title for the dialog.
+*/
+
+QString QQuickWebEngineJavaScriptDialogRequest::title() const
+{
+ return m_title;
+}
+
+/*!
+ \qmlproperty enumeration JavaScriptDialogRequest::type
+ \readonly
+
+ Returns the type of the requested dialog box, see HTML5's
+
+ \l{https://www.w3.org/TR/html5/webappapis.html#simple-dialogs}{Simple Dialogs}.
+
+ \value JavaScriptDialogRequest.DialogTypeAlert
+ A JavaScript alert dialog.
+ \value JavaScriptDialogRequest.DialogTypeConfirm
+ A JavaScript confirmation dialog.
+ \value JavaScriptDialogRequest.DialogTypePrompt
+ A JavaScript prompt dialog.
+ \value JavaScriptDialogRequest.DialogTypeUnload
+ The users should be asked if they want to leave the page.
+*/
+
+QQuickWebEngineJavaScriptDialogRequest::DialogType QQuickWebEngineJavaScriptDialogRequest::type() const
+{
+ return m_type;
+}
+
+/*!
+ \qmlproperty url JavaScriptDialogRequest::securityOrigin
+ \readonly
+
+ The URL of the security origin.
+*/
+
+QUrl QQuickWebEngineJavaScriptDialogRequest::securityOrigin() const
+{
+ return m_securityOrigin;
+}
+
+/*!
+ \qmlproperty bool JavaScriptDialogRequest::accepted
+
+ Indicates whether the JavaScript dialog request has been
+ accepted by the signal handler.
+
+ If the property is \c false after any signal handlers
+ for WebEngineView::javaScriptDialogRequested have been executed,
+ a default dialog will be shown.
+ To prevent this, set \c{request.accepted} to \c true.
+
+ The default is \c false.
+*/
+
+bool QQuickWebEngineJavaScriptDialogRequest::isAccepted() const
+{
+ return m_accepted;
+}
+
+void QQuickWebEngineJavaScriptDialogRequest::setAccepted(bool accepted)
+{
+ m_accepted = accepted;
+}
+
+/*!
+ \qmlmethod void JavaScriptDialogRequest::dialogAccept()
+
+ This function notifies the engine that the user accepted the dialog.
+*/
+
+/*!
+ \qmlmethod void JavaScriptDialogRequest::dialogAccept(string text)
+
+ This function notifies the engine that the user accepted the dialog,
+ providing the \a text in case of a prompt message box.
+*/
+
+void QQuickWebEngineJavaScriptDialogRequest::dialogAccept(const QString& text)
+{
+ m_accepted = true;
+ QSharedPointer<JavaScriptDialogController> controller
+ = m_controller.toStrongRef();
+ if (controller) {
+ controller->textProvided(text);
+ controller->accept();
+ }
+}
+
+/*!
+ \qmlmethod void JavaScriptDialogRequest::dialogReject()
+
+ This function notifies the engine that the user rejected the dialog.
+*/
+
+void QQuickWebEngineJavaScriptDialogRequest::dialogReject()
+{
+ m_accepted = true;
+ QSharedPointer<JavaScriptDialogController> controller
+ = m_controller.toStrongRef();
+ if (controller)
+ controller->reject();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \qmltype ColorDialogRequest
+ \instantiates QQuickWebEngineColorDialogRequest
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.4
+
+ \brief A request for selecting a color by the user.
+
+ A ColorDialogRequest is passed as an argument of the
+ WebEngineView::colorDialogRequested signal. It is generated when
+ a color picker dialog is requested. See
+ \l { https://www.w3.org/TR/html5/forms.html#color-state-(type=color)}
+ {HTML5 Color State}.
+
+ The \l accepted property of the request indicates whether the request
+ is handled by the user code or the default dialog should be displayed.
+ If you set the \l accepted property to \c true, make sure to call either
+ \l dialogAccept() or \l dialogReject() afterwards.
+
+ The following code uses a custom dialog to handle the request:
+
+ \code
+ WebEngineView {
+ // ...
+ onColorDialogRequested: function(request) {
+ request.accepted = true;
+ myDialog.request = request // keep the reference to the request
+ myDialog.accept.connect(request.dialogAccept);
+ myDialog.reject.connect(request.dialogReject);
+ myDialog.visible = true;
+ }
+ // ...
+ }
+ \endcode
+*/
+
+QQuickWebEngineColorDialogRequest::QQuickWebEngineColorDialogRequest(
+ QSharedPointer<ColorChooserController> controller, QObject *parent):
+ QObject(parent)
+ , m_controller(controller.toWeakRef())
+ , m_color(controller->initialColor())
+ , m_accepted(false)
+{
+
+}
+
+QQuickWebEngineColorDialogRequest::~QQuickWebEngineColorDialogRequest()
+{
+
+}
+
+/*!
+ \qmlproperty color ColorDialogRequest::color
+ \readonly
+
+ The default color to be selected in the dialog.
+*/
+
+QColor QQuickWebEngineColorDialogRequest::color() const
+{
+ return m_color;
+}
+
+/*!
+ \qmlproperty bool ColorDialogRequest::accepted
+
+ Indicates whether the color picker dialog request has been
+ accepted by the signal handler.
+
+ If the property is \c false after any signal handlers
+ for WebEngineView::colorDialogRequested have been executed,
+ a default color picker dialog will be shown.
+ To prevent this, set \c{request.accepted} to \c true.
+
+ The default is \c false.
+*/
+
+bool QQuickWebEngineColorDialogRequest::isAccepted() const
+{
+ return m_accepted;
+}
+
+void QQuickWebEngineColorDialogRequest::setAccepted(bool accepted)
+{
+ m_accepted = accepted;
+}
+
+
+/*!
+ \qmlmethod void ColorDialogRequest::dialogAccept(color color)
+
+ This function notifies the engine that the user accepted the dialog,
+ providing the \a color.
+*/
+
+void QQuickWebEngineColorDialogRequest::dialogAccept(const QColor &color)
+{
+ m_accepted = true;
+ QSharedPointer<ColorChooserController> controller = m_controller.toStrongRef();
+ if (controller)
+ controller->accept(color);
+}
+
+/*!
+ \qmlmethod void ColorDialogRequest::dialogReject()
+
+ This function notifies the engine that the user rejected the dialog.
+*/
+
+void QQuickWebEngineColorDialogRequest::dialogReject()
+{
+ m_accepted = true;
+ QSharedPointer<ColorChooserController> controller = m_controller.toStrongRef();
+ if (controller)
+ controller->reject();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \qmltype FileDialogRequest
+ \instantiates QQuickWebEngineFileDialogRequest
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.4
+
+ \brief A request for letting the user choose a (new or existing) file or
+ directory.
+
+ A FileDialogRequest is passed as an argument of the
+ WebEngineView::fileDialogRequested signal. It is generated
+ when the file dialog is requested by the input element.
+ See \l {https://www.w3.org/TR/html5/forms.html#file-upload-state-(type=file)}{File Upload state}.
+
+ The \l accepted property of the request indicates whether the request
+ is handled by the user code or the default dialog should be displayed.
+ If you set the \l accepted property to \c true, make sure to call either
+ \l dialogAccept() or \l dialogReject() afterwards.
+
+ The following code uses a custom dialog to handle the request:
+
+ \code
+ WebEngineView {
+ // ...
+ onFileDialogRequested: function(request) {
+ request.accepted = true;
+ myDialog.request = request // keep the reference to the request
+ myDialog.accept.connect(request.dialogAccept);
+ myDialog.reject.connect(request.dialogReject);
+ myDialog.visible = true;
+ }
+ // ...
+ }
+ \endcode
+*/
+
+QQuickWebEngineFileDialogRequest::QQuickWebEngineFileDialogRequest(
+ QSharedPointer<FilePickerController> controller, QObject *parent):
+ QObject(parent)
+ , m_controller(controller.toWeakRef())
+ , m_filename(controller->defaultFileName())
+ , m_acceptedMimeTypes(controller->acceptedMimeTypes())
+ , m_mode(static_cast<QQuickWebEngineFileDialogRequest::FileMode>(controller->mode()))
+ , m_accepted(false)
+{
+
+}
+
+QQuickWebEngineFileDialogRequest::~QQuickWebEngineFileDialogRequest()
+{
+
+}
+
+/*!
+ \qmlproperty stringlist FileDialogRequest::acceptedMimeTypes
+ \readonly
+
+ A list of MIME types specified in the input element. The selection
+ should be restricted to only these types of files.
+*/
+
+QStringList QQuickWebEngineFileDialogRequest::acceptedMimeTypes() const
+{
+ return m_acceptedMimeTypes;
+}
+
+/*!
+ \qmlproperty string FileDialogRequest::defaultFileName
+ \readonly
+
+ The default name of the file to be selected in the dialog.
+*/
+
+QString QQuickWebEngineFileDialogRequest::defaultFileName() const
+{
+ return m_filename;
+}
+
+/*!
+ \qmlproperty enumeration FileDialogRequest::mode
+ \readonly
+
+ The mode of the file dialog.
+
+ \value FileDialogRequest.FileModeOpen
+ Allows users to specify a single existing file.
+ \value FileDialogRequest.FileModeOpenMultiple
+ Allows users to specify multiple existing files.
+ \value FileDialogRequest.FileModeUploadFolder
+ Allows users to specify a single existing folder for upload.
+ \value FileDialogRequest.FileModeSave
+ Allows users to specify a non-existing file. If an existing file
+ is selected, the users should be informed that the file is going
+ to be overwritten.
+*/
+
+QQuickWebEngineFileDialogRequest::FileMode QQuickWebEngineFileDialogRequest::mode() const
+{
+ return m_mode;
+}
+
+/*!
+ \qmlproperty bool FileDialogRequest::accepted
+
+ Indicates whether the file picker dialog request has been
+ handled by the signal handler.
+
+ If the property is \c false after any signal handlers
+ for WebEngineView::fileDialogRequested have been executed,
+ a default file picker dialog will be shown.
+ To prevent this, set \c{request.accepted} to \c true.
+
+ The default is \c false.
+*/
+
+bool QQuickWebEngineFileDialogRequest::isAccepted() const
+{
+ return m_accepted;
+}
+
+void QQuickWebEngineFileDialogRequest::setAccepted(bool accepted)
+{
+ m_accepted = accepted;
+}
+
+/*!
+ \qmlmethod void FileDialogRequest::dialogAccept(stringlist files)
+
+ This function needs to be called when the user accepted the dialog with
+ \a files.
+*/
+
+void QQuickWebEngineFileDialogRequest::dialogAccept(const QStringList &files)
+{
+ m_accepted = true;
+ QSharedPointer<FilePickerController> controller = m_controller.toStrongRef();
+ if (controller)
+ controller->accepted(files);
+}
+
+/*!
+ \qmlmethod void FileDialogRequest::dialogReject()
+
+ This function needs to be called when the user did not accepted the dialog.
+*/
+
+void QQuickWebEngineFileDialogRequest::dialogReject()
+{
+ m_accepted = true;
+ QSharedPointer<FilePickerController> controller = m_controller.toStrongRef();
+ if (controller)
+ controller->rejected();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*!
+ \qmltype FormValidationMessageRequest
+ \instantiates QQuickWebEngineFormValidationMessageRequest
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.4
+
+ \brief A request for showing a HTML5 form validation message to the user.
+
+ A FormValidationMessageRequest is passed as an argument of the
+ WebEngineView::formValidationMessageRequested signal. It is generated when
+ the handling of the validation message is requested.
+
+ The \l accepted property of the request indicates whether the request
+ is handled by the user code or the default message should be displayed.
+
+ The following code uses a custom message to handle the request:
+
+ \code
+ WebEngineView {
+ // ...
+ onFormValidationMessageRequested: function(request) {
+ request.accepted = true;
+ switch (request.type) {
+ case FormValidationMessageRequest.RequestTypeShow:
+ validationMessgae.text = request.text;
+ validationMessgae.x = request.x;
+ validationMessage.y = request.y
+ validationMessgae.visible = true;
+ break;
+ case FormValidationMessageRequest.RequestTypeMove:
+ break;
+ case FormValidationMessageRequest.RequestTypeHide:
+ validationMessgae.visible = false;
+ break;
+ }
+ }
+ // ...
+ }
+ \endcode
+*/
+
+QQuickWebEngineFormValidationMessageRequest::QQuickWebEngineFormValidationMessageRequest(
+ QQuickWebEngineFormValidationMessageRequest::RequestType type, const QRect& anchor,
+ const QString &mainText, const QString &subText, QObject *parent):
+ QObject(parent)
+ , m_anchor(anchor)
+ , m_mainText(mainText)
+ , m_subText(subText)
+ , m_type(type)
+ , m_accepted(false)
+{
+
+}
+
+QQuickWebEngineFormValidationMessageRequest::~QQuickWebEngineFormValidationMessageRequest()
+{
+
+}
+
+/*!
+ \qmlproperty rectangle FormValidationMessageRequest::anchor
+ \readonly
+
+ An anchor of an element in the viewport for which the form
+ validation message should be displayed.
+*/
+
+QRect QQuickWebEngineFormValidationMessageRequest::anchor() const
+{
+ return m_anchor;
+}
+
+/*!
+ \qmlproperty bool FormValidationMessageRequest::text
+ \readonly
+
+ The text of the form validation message.
+*/
+
+
+QString QQuickWebEngineFormValidationMessageRequest::text() const
+{
+ return m_mainText;
+}
+
+/*!
+ \qmlproperty bool FormValidationMessageRequest::subText
+ \readonly
+
+ The subtext of the form validation message.
+*/
+
+
+QString QQuickWebEngineFormValidationMessageRequest::subText() const
+{
+ return m_subText;
+}
+
+/*!
+ \qmlproperty enumeration ValidationMessageRequest::type
+ \readonly
+
+ The type of the form validation message request.
+
+ \value ValidationMessageRequest.RequestTypeShow
+ The form validation message should be shown.
+ \value ValidationMessageRequest.RequestTypeHide
+ The form validation message should be hidden.
+ \value ValidationMessageRequest.RequestTypeMove
+ The form validation message should be moved.
+*/
+
+QQuickWebEngineFormValidationMessageRequest::RequestType QQuickWebEngineFormValidationMessageRequest::type() const
+{
+ return m_type;
+}
+
+/*!
+ \qmlproperty bool FormValidationMessageRequest::accepted
+
+ Indicates whether the form validation request has been
+ accepted by the signal handler.
+
+ If the property is \c false after any signal handlers
+ for WebEngineView::validationMessageRequested have been executed,
+ a default file validation message will be shown.
+ To prevent this, set \c {request.accepted} to \c true.
+
+ The default is \c false.
+*/
+
+bool QQuickWebEngineFormValidationMessageRequest::isAccepted() const
+{
+ return m_accepted;
+}
+
+void QQuickWebEngineFormValidationMessageRequest::setAccepted(bool accepted)
+{
+ m_accepted = accepted;
+}
+
+QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginedialogrequests_p.h b/src/webengine/api/qquickwebenginedialogrequests_p.h
new file mode 100644
index 000000000..d1ddc6607
--- /dev/null
+++ b/src/webengine/api/qquickwebenginedialogrequests_p.h
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QQUICKWEBENGINDIALOGREQUESTS_H
+#define QQUICKWEBENGINDIALOGREQUESTS_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 <private/qtwebengineglobal_p.h>
+#include <QtCore/QUrl>
+#include <QtCore/QWeakPointer>
+#include <QtCore/QRect>
+#include <QtGui/QColor>
+
+namespace QtWebEngineCore {
+ class AuthenticationDialogController;
+ class ColorChooserController;
+ class FilePickerController;
+ class JavaScriptDialogController;
+}
+
+QT_BEGIN_NAMESPACE
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineAuthenticationDialogRequest : public QObject {
+ Q_OBJECT
+public:
+
+ enum AuthenticationType {
+ AuthenticationTypeHTTP,
+ AuthenticationTypeProxy
+ };
+
+ Q_ENUM(AuthenticationType)
+
+ Q_PROPERTY(QUrl url READ url CONSTANT FINAL)
+ Q_PROPERTY(QString realm READ realm CONSTANT FINAL)
+ Q_PROPERTY(QString proxyHost READ proxyHost CONSTANT FINAL)
+ Q_PROPERTY(AuthenticationType type READ type CONSTANT FINAL)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL)
+
+ ~QQuickWebEngineAuthenticationDialogRequest();
+
+ QUrl url() const;
+ QString realm() const;
+ QString proxyHost() const;
+ AuthenticationType type() const;
+ bool isAccepted() const;
+ void setAccepted(bool accepted);
+
+public slots:
+ void dialogAccept(const QString &user, const QString &password);
+ void dialogReject();
+
+private:
+ QQuickWebEngineAuthenticationDialogRequest(QSharedPointer<QtWebEngineCore::AuthenticationDialogController> controller,
+ QObject *parent = nullptr);
+ QWeakPointer<QtWebEngineCore::AuthenticationDialogController> m_controller;
+ QUrl m_url;
+ QString m_realm;
+ AuthenticationType m_type;
+ QString m_host;
+ bool m_accepted;
+ friend class QQuickWebEngineViewPrivate;
+ Q_DISABLE_COPY(QQuickWebEngineAuthenticationDialogRequest)
+};
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineJavaScriptDialogRequest : public QObject {
+ Q_OBJECT
+public:
+
+ enum DialogType {
+ DialogTypeAlert,
+ DialogTypeConfirm,
+ DialogTypePrompt,
+ DialogTypeBeforeUnload,
+ };
+ Q_ENUM(DialogType)
+
+ Q_PROPERTY(QString message READ message CONSTANT FINAL)
+ Q_PROPERTY(QString defaultText READ defaultText CONSTANT FINAL)
+ Q_PROPERTY(QString title READ title CONSTANT FINAL)
+ Q_PROPERTY(DialogType type READ type CONSTANT FINAL)
+ Q_PROPERTY(QUrl securityOrigin READ securityOrigin CONSTANT FINAL)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL)
+
+ ~QQuickWebEngineJavaScriptDialogRequest();
+
+ QString message() const;
+ QString defaultText() const;
+ QString title() const;
+ DialogType type() const;
+ QUrl securityOrigin() const;
+ bool isAccepted() const;
+ void setAccepted(bool accepted);
+
+public slots:
+ void dialogAccept(const QString& text = QString());
+ void dialogReject();
+
+private:
+ QQuickWebEngineJavaScriptDialogRequest(QSharedPointer<QtWebEngineCore::JavaScriptDialogController> controller,
+ QObject *parent = nullptr);
+ QWeakPointer<QtWebEngineCore::JavaScriptDialogController> m_controller;
+ QString m_message;
+ QString m_defaultPrompt;
+ QString m_title;
+ DialogType m_type;
+ QUrl m_securityOrigin;
+ bool m_accepted;
+ friend class QQuickWebEngineViewPrivate;
+ Q_DISABLE_COPY(QQuickWebEngineJavaScriptDialogRequest)
+};
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineColorDialogRequest : public QObject {
+ Q_OBJECT
+public:
+
+ Q_PROPERTY(QColor color READ color CONSTANT FINAL)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL)
+
+ ~QQuickWebEngineColorDialogRequest();
+
+ QColor color() const;
+ bool isAccepted() const;
+ void setAccepted(bool accepted);
+
+public slots:
+ void dialogAccept(const QColor &color);
+ void dialogReject();
+
+private:
+ QQuickWebEngineColorDialogRequest(QSharedPointer<QtWebEngineCore::ColorChooserController> controller,
+ QObject *parent = nullptr);
+ QWeakPointer<QtWebEngineCore::ColorChooserController> m_controller;
+ QColor m_color;
+ bool m_accepted;
+ friend class QQuickWebEngineViewPrivate;
+ Q_DISABLE_COPY(QQuickWebEngineColorDialogRequest)
+};
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineFileDialogRequest : public QObject {
+ Q_OBJECT
+public:
+
+ enum FileMode {
+ FileModeOpen,
+ FileModeOpenMultiple,
+ FileModeUploadFolder,
+ FileModeSave
+ };
+ Q_ENUM(FileMode)
+
+ Q_PROPERTY(QString defaultFileName READ defaultFileName CONSTANT FINAL)
+ Q_PROPERTY(QStringList acceptedMimeTypes READ acceptedMimeTypes CONSTANT FINAL)
+ Q_PROPERTY(FileMode mode READ mode CONSTANT FINAL)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL)
+
+ ~QQuickWebEngineFileDialogRequest();
+
+ QStringList acceptedMimeTypes() const;
+ QString defaultFileName() const;
+ FileMode mode() const;
+ bool isAccepted() const;
+ void setAccepted(bool accepted);
+
+public slots:
+ void dialogAccept(const QStringList &files);
+ void dialogReject();
+
+private:
+ QQuickWebEngineFileDialogRequest(QSharedPointer<QtWebEngineCore::FilePickerController> controller,
+ QObject *parent = nullptr);
+ QWeakPointer<QtWebEngineCore::FilePickerController> m_controller;
+ QString m_filename;
+ QStringList m_acceptedMimeTypes;
+ FileMode m_mode;
+ bool m_accepted;
+ friend class QQuickWebEngineViewPrivate;
+ Q_DISABLE_COPY(QQuickWebEngineFileDialogRequest)
+};
+
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineFormValidationMessageRequest : public QObject {
+ Q_OBJECT
+public:
+ enum RequestType {
+ RequestTypeShow,
+ RequestTypeHide,
+ RequestTypeMove,
+ };
+ Q_ENUM(RequestType)
+ Q_PROPERTY(QRect anchor READ anchor CONSTANT FINAL)
+ Q_PROPERTY(QString text READ text CONSTANT FINAL)
+ Q_PROPERTY(QString subText READ subText CONSTANT FINAL)
+ Q_PROPERTY(RequestType type READ type CONSTANT FINAL)
+ Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted FINAL)
+
+ ~QQuickWebEngineFormValidationMessageRequest();
+ QRect anchor() const;
+ QString text() const;
+ QString subText() const;
+ RequestType type() const;
+ bool isAccepted() const;
+ void setAccepted(bool accepted);
+
+private:
+ QQuickWebEngineFormValidationMessageRequest(RequestType type, const QRect &anchor = QRect(),
+ const QString &mainText = QString(),
+ const QString &subText = QString(),
+ QObject *parent = nullptr);
+ QRect m_anchor;
+ QString m_mainText;
+ QString m_subText;
+ RequestType m_type;
+ bool m_accepted;
+ friend class QQuickWebEngineViewPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QQUICKWEBENGINDIALOGREQUESTS_H
diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp
index a8467d656..f38af3923 100644
--- a/src/webengine/api/qquickwebenginedownloaditem.cpp
+++ b/src/webengine/api/qquickwebenginedownloaditem.cpp
@@ -66,6 +66,7 @@ QQuickWebEngineDownloadItemPrivate::QQuickWebEngineDownloadItemPrivate(QQuickWeb
, downloadId(-1)
, downloadState(QQuickWebEngineDownloadItem::DownloadCancelled)
, savePageFormat(QQuickWebEngineDownloadItem::UnknownSaveFormat)
+ , type(QQuickWebEngineDownloadItem::Attachment)
, totalBytes(-1)
, receivedBytes(0)
{
@@ -299,6 +300,29 @@ void QQuickWebEngineDownloadItem::setSavePageFormat(QQuickWebEngineDownloadItem:
}
}
+/*!
+ \qmlproperty enumeration WebEngineDownloadItem::type
+ \readonly
+ \since QtWebEngine 1.4
+
+ Describes the requested download's type.
+
+ \value Attachment The web server's response includes a \c Content-Disposition header with the \c attachment directive.
+ If \c Content-Disposition is present in the reply, the web server is indicating that
+ the client should prompt the user to save the content regardless of the content type.
+ See \l {RFC 2616 section 19.5.1} for details.
+ \value DownloadAttribute The user clicked the hyperlink.
+ See \l {HTML download Attribute} for details.
+ \value UserRequested The user initiated the download.
+ \value SavePage The user saved a web page.
+ */
+
+QQuickWebEngineDownloadItem::DownloadType QQuickWebEngineDownloadItem::type() const
+{
+ Q_D(const QQuickWebEngineDownloadItem);
+ return d->type;
+}
+
QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate *p, QObject *parent)
: QObject(parent)
, d_ptr(p)
diff --git a/src/webengine/api/qquickwebenginedownloaditem_p.h b/src/webengine/api/qquickwebenginedownloaditem_p.h
index 0b01fe6fc..61e019b9e 100644
--- a/src/webengine/api/qquickwebenginedownloaditem_p.h
+++ b/src/webengine/api/qquickwebenginedownloaditem_p.h
@@ -82,6 +82,14 @@ public:
};
Q_ENUM(SavePageFormat)
+ enum DownloadType {
+ Attachment = 0,
+ DownloadAttribute,
+ UserRequested,
+ SavePage
+ };
+ Q_ENUM(DownloadType)
+
Q_PROPERTY(quint32 id READ id CONSTANT FINAL)
Q_PROPERTY(DownloadState state READ state NOTIFY stateChanged)
Q_PROPERTY(SavePageFormat savePageFormat READ savePageFormat WRITE setSavePageFormat NOTIFY savePageFormatChanged REVISION 2 FINAL)
@@ -89,6 +97,7 @@ public:
Q_PROPERTY(qint64 receivedBytes READ receivedBytes NOTIFY receivedBytesChanged)
Q_PROPERTY(QString mimeType READ mimeType NOTIFY mimeTypeChanged REVISION 1)
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
+ Q_PROPERTY(DownloadType type READ type NOTIFY typeChanged REVISION 3 FINAL)
Q_INVOKABLE void accept();
Q_INVOKABLE void cancel();
@@ -102,6 +111,7 @@ public:
void setPath(QString path);
SavePageFormat savePageFormat() const;
void setSavePageFormat(SavePageFormat format);
+ DownloadType type() const;
Q_SIGNALS:
void stateChanged();
@@ -110,6 +120,7 @@ Q_SIGNALS:
void totalBytesChanged();
Q_REVISION(1) void mimeTypeChanged();
void pathChanged();
+ Q_REVISION(3) void typeChanged();
private:
QQuickWebEngineDownloadItem(QQuickWebEngineDownloadItemPrivate*, QObject *parent = 0);
diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
index bdae54ca4..1789af462 100644
--- a/src/webengine/api/qquickwebenginedownloaditem_p_p.h
+++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
@@ -73,6 +73,7 @@ public:
quint32 downloadId;
QQuickWebEngineDownloadItem::DownloadState downloadState;
QQuickWebEngineDownloadItem::SavePageFormat savePageFormat;
+ QQuickWebEngineDownloadItem::DownloadType type;
qint64 totalBytes;
qint64 receivedBytes;
QString mimeType;
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index 191105e52..32161570d 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -85,6 +85,10 @@ ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::MimeHtmlSaveFormat, QtWebEngineC
QQuickWebEngineProfile class, which exposes further functionality in C++. This allows Qt Quick
applications to intercept URL requests (QQuickWebEngineProfile::setRequestInterceptor), or
register custom URL schemes (QQuickWebEngineProfile::installUrlSchemeHandler).
+
+ Spellchecking HTML form fields can be enabled per profile by setting the \l spellCheckEnabled
+ property and the current language used for spellchecking can be set by using the
+ \l spellCheckLanguage property.
*/
/*!
@@ -180,6 +184,7 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
itemPrivate->downloadPath = info.path;
itemPrivate->savePageFormat = static_cast<QQuickWebEngineDownloadItem::SavePageFormat>(
info.savePageFormat);
+ itemPrivate->type = static_cast<QQuickWebEngineDownloadItem::DownloadType>(info.downloadType);
QQuickWebEngineDownloadItem *download = new QQuickWebEngineDownloadItem(itemPrivate, q);
@@ -613,6 +618,85 @@ QQuickWebEngineProfile *QQuickWebEngineProfile::defaultProfile()
}
/*!
+ \property QQuickWebEngineProfile::spellCheckLanguage
+ \brief the language used by the spell checker.
+
+ \since QtWebEngine 1.4
+*/
+
+/*!
+ \qmlproperty QString WebEngineProfile::spellCheckLanguage
+
+ This property holds the language used by the spell checker.
+ The language should match the name of the \c .bdic dictionary.
+ For example, the \a language \c en-US will load the \c en-US.bdic
+ dictionary file.
+
+ The web engine checks for the \c qtwebengine_dictionaries subdirectory
+ first in the local directory and if it is not found in the Qt
+ installation directory:
+
+ \list
+ \li QCoreApplication::applicationDirPath()/qtwebengine_dictionaries
+ \li [QLibraryInfo::DataPath]/qtwebengine_dictionaries
+ \endlist
+
+ For more information about how to compile \c .bdic dictionaries, see the
+ \l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}.
+
+ \since QtWebEngine 1.4
+*/
+void QQuickWebEngineProfile::setSpellCheckLanguage(const QString &language)
+{
+ Q_D(QQuickWebEngineProfile);
+ if (language != d->browserContext()->spellCheckLanguage()) {
+ d->browserContext()->setSpellCheckLanguage(language);
+ emit spellCheckLanguageChanged();
+ }
+}
+
+/*!
+ \since 5.8
+
+ Returns the language used by the spell checker.
+*/
+QString QQuickWebEngineProfile::spellCheckLanguage() const
+{
+ const Q_D(QQuickWebEngineProfile);
+ return d->browserContext()->spellCheckLanguage();
+}
+
+/*!
+ \property QQuickWebEngineProfile::spellCheckEnabled
+ \brief whether the web engine spell checker is enabled.
+
+ \since QtWebEngine 1.4
+*/
+
+/*!
+ \qmlproperty QString WebEngineProfile::spellCheckEnabled
+
+ This property holds whether the web engine spell checker is enabled.
+
+ \since QtWebEngine 1.4
+*/
+void QQuickWebEngineProfile::setSpellCheckEnabled(bool enable)
+{
+ Q_D(QQuickWebEngineProfile);
+ if (enable != isSpellCheckEnabled()) {
+ d->browserContext()->setSpellCheckEnabled(enable);
+ emit spellCheckEnabledChanged();
+ }
+}
+
+bool QQuickWebEngineProfile::isSpellCheckEnabled() const
+{
+ const Q_D(QQuickWebEngineProfile);
+ return d->browserContext()->isSpellCheckEnabled();
+}
+
+/*!
+
Returns the cookie store for this profile.
*/
QWebEngineCookieStore *QQuickWebEngineProfile::cookieStore() const
diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h
index dc5aa7df8..2b0dbf9d4 100644
--- a/src/webengine/api/qquickwebengineprofile.h
+++ b/src/webengine/api/qquickwebengineprofile.h
@@ -71,6 +71,8 @@ class Q_WEBENGINE_EXPORT QQuickWebEngineProfile : public QObject {
Q_PROPERTY(QString httpAcceptLanguage READ httpAcceptLanguage WRITE setHttpAcceptLanguage NOTIFY httpAcceptLanguageChanged FINAL REVISION 1)
Q_PROPERTY(PersistentCookiesPolicy persistentCookiesPolicy READ persistentCookiesPolicy WRITE setPersistentCookiesPolicy NOTIFY persistentCookiesPolicyChanged FINAL)
Q_PROPERTY(int httpCacheMaximumSize READ httpCacheMaximumSize WRITE setHttpCacheMaximumSize NOTIFY httpCacheMaximumSizeChanged FINAL)
+ Q_PROPERTY(QString spellCheckLanguage READ spellCheckLanguage WRITE setSpellCheckLanguage NOTIFY spellCheckLanguageChanged FINAL REVISION 3)
+ Q_PROPERTY(bool spellCheckEnabled READ isSpellCheckEnabled WRITE setSpellCheckEnabled NOTIFY spellCheckEnabledChanged FINAL REVISION 3)
public:
QQuickWebEngineProfile(QObject *parent = Q_NULLPTR);
@@ -129,6 +131,11 @@ public:
Q_REVISION(2) Q_INVOKABLE void clearHttpCache();
+ Q_REVISION(3) void setSpellCheckLanguage(const QString &language);
+ Q_REVISION(3) QString spellCheckLanguage() const;
+ Q_REVISION(3) void setSpellCheckEnabled(bool enabled);
+ Q_REVISION(3) bool isSpellCheckEnabled() const;
+
static QQuickWebEngineProfile *defaultProfile();
Q_SIGNALS:
@@ -141,6 +148,8 @@ Q_SIGNALS:
void persistentCookiesPolicyChanged();
void httpCacheMaximumSizeChanged();
Q_REVISION(1) void httpAcceptLanguageChanged();
+ Q_REVISION(3) void spellCheckLanguageChanged();
+ Q_REVISION(3) void spellCheckEnabledChanged();
void downloadRequested(QQuickWebEngineDownloadItem *download);
void downloadFinished(QQuickWebEngineDownloadItem *download);
diff --git a/src/webengine/api/qquickwebenginescript.cpp b/src/webengine/api/qquickwebenginescript.cpp
index 7e08e2fd5..8ec5d1fe7 100644
--- a/src/webengine/api/qquickwebenginescript.cpp
+++ b/src/webengine/api/qquickwebenginescript.cpp
@@ -65,7 +65,8 @@ using QtWebEngineCore::UserScript;
not accessible from a different one. The worldId property provides some predefined IDs for this
purpose.
- \note Chromium extensions, such as \c @include, \c @match, and \c @exclude, are not supported.
+ The following Chromium extensions are supported since Qt 5.8: \c @exclude, \c @include,
+ \c @name, \c @match, and \c @run-at.
Use \l{WebEngineView::userScripts}{WebEngineView.userScripts} to access a list of scripts
attached to the web view.
diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp
index 09fb2b98d..7aa4d2a96 100644
--- a/src/webengine/api/qquickwebenginesettings.cpp
+++ b/src/webengine/api/qquickwebenginesettings.cpp
@@ -304,6 +304,33 @@ bool QQuickWebEngineSettings::touchIconsEnabled() const
}
/*!
+ \qmlproperty bool WebEngineSettings::focusOnNavigationEnabled
+ \since QtWebEngine 1.4
+
+ Focus is given to the view whenever a navigation operation occurs
+ (load, stop, reload, reload and bypass cache, forward, backward, set content, and so on).
+
+ Enabled by default.
+*/
+bool QQuickWebEngineSettings::focusOnNavigationEnabled() const
+{
+ return d_ptr->testAttribute(WebEngineSettings::FocusOnNavigationEnabled);
+}
+
+/*!
+ \qmlproperty bool WebEngineSettings::printElementBackgrounds
+ \since QtWebEngine 1.4
+
+ Turns on printing of CSS backgrounds when printing a web page.
+
+ Enabled by default.
+*/
+bool QQuickWebEngineSettings::printElementBackgrounds() const
+{
+ return d_ptr->testAttribute(WebEngineSettings::PrintElementBackgrounds);
+}
+
+/*!
\qmlproperty QString WebEngineSettings::defaultTextEncoding
\since QtWebEngine 1.2
@@ -464,6 +491,14 @@ void QQuickWebEngineSettings::setTouchIconsEnabled(bool on)
Q_EMIT touchIconsEnabledChanged();
}
+void QQuickWebEngineSettings::setPrintElementBackgrounds(bool on)
+{
+ bool wasOn = d_ptr->testAttribute(WebEngineSettings::PrintElementBackgrounds);
+ d_ptr->setAttribute(WebEngineSettings::PrintElementBackgrounds, on);
+ if (wasOn != on)
+ Q_EMIT printElementBackgroundsChanged();
+}
+
void QQuickWebEngineSettings::setDefaultTextEncoding(QString encoding)
{
const QString oldDefaultTextEncoding = d_ptr->defaultTextEncoding();
@@ -472,6 +507,14 @@ void QQuickWebEngineSettings::setDefaultTextEncoding(QString encoding)
Q_EMIT defaultTextEncodingChanged();
}
+void QQuickWebEngineSettings::setFocusOnNavigationEnabled(bool on)
+{
+ bool wasOn = d_ptr->testAttribute(WebEngineSettings::FocusOnNavigationEnabled);
+ d_ptr->setAttribute(WebEngineSettings::FocusOnNavigationEnabled, on);
+ if (wasOn != on)
+ Q_EMIT focusOnNavigationEnabledChanged();
+}
+
void QQuickWebEngineSettings::setParentSettings(QQuickWebEngineSettings *parentSettings)
{
d_ptr->setParentSettings(parentSettings->d_ptr.data());
diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h
index 584027260..917b9e443 100644
--- a/src/webengine/api/qquickwebenginesettings_p.h
+++ b/src/webengine/api/qquickwebenginesettings_p.h
@@ -82,6 +82,8 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject {
Q_PROPERTY(bool accelerated2dCanvasEnabled READ accelerated2dCanvasEnabled WRITE setAccelerated2dCanvasEnabled NOTIFY accelerated2dCanvasEnabledChanged REVISION 2)
Q_PROPERTY(bool autoLoadIconsForPage READ autoLoadIconsForPage WRITE setAutoLoadIconsForPage NOTIFY autoLoadIconsForPageChanged REVISION 2)
Q_PROPERTY(bool touchIconsEnabled READ touchIconsEnabled WRITE setTouchIconsEnabled NOTIFY touchIconsEnabledChanged REVISION 2)
+ Q_PROPERTY(bool focusOnNavigationEnabled READ focusOnNavigationEnabled WRITE setFocusOnNavigationEnabled NOTIFY focusOnNavigationEnabledChanged REVISION 3)
+ Q_PROPERTY(bool printElementBackgrounds READ printElementBackgrounds WRITE setPrintElementBackgrounds NOTIFY printElementBackgroundsChanged REVISION 3)
public:
~QQuickWebEngineSettings();
@@ -105,6 +107,8 @@ public:
bool accelerated2dCanvasEnabled() const;
bool autoLoadIconsForPage() const;
bool touchIconsEnabled() const;
+ bool focusOnNavigationEnabled() const;
+ bool printElementBackgrounds() const;
void setAutoLoadImages(bool on);
void setJavascriptEnabled(bool on);
@@ -125,6 +129,8 @@ public:
void setAccelerated2dCanvasEnabled(bool on);
void setAutoLoadIconsForPage(bool on);
void setTouchIconsEnabled(bool on);
+ void setFocusOnNavigationEnabled(bool on);
+ void setPrintElementBackgrounds(bool on);
signals:
void autoLoadImagesChanged();
@@ -146,6 +152,8 @@ signals:
Q_REVISION(2) void accelerated2dCanvasEnabledChanged();
Q_REVISION(2) void autoLoadIconsForPageChanged();
Q_REVISION(2) void touchIconsEnabledChanged();
+ Q_REVISION(3) void focusOnNavigationEnabledChanged();
+ Q_REVISION(3) void printElementBackgroundsChanged();
private:
explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = 0);
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index 5087199cc..fd1e746a8 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -47,6 +47,8 @@
#include "javascript_dialog_controller.h"
#include "qquickwebenginehistory_p.h"
#include "qquickwebenginecertificateerror_p.h"
+#include "qquickwebenginecontextmenurequest_p.h"
+#include "qquickwebenginedialogrequests_p.h"
#include "qquickwebenginefaviconprovider_p_p.h"
#include "qquickwebengineloadrequest_p.h"
#include "qquickwebenginenavigationrequest_p.h"
@@ -145,8 +147,7 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate()
, m_dpiScale(1.0)
, m_backgroundColor(Qt::white)
, m_defaultZoomFactor(1.0)
- // QTBUG-53467
- , m_menuEnabled(true)
+ , m_ui2Enabled(false)
{
// The gold standard for mobile web content is 160 dpi, and the devicePixelRatio expected
// is the (possibly quantized) ratio of device dpi to 160 dpi.
@@ -164,8 +165,26 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate()
// 1x, 2x, 3x etc assets that fit an integral number of pixels.
setDevicePixelRatio(qMax(1, qRound(webPixelRatio)));
}
+
if (platform == QLatin1Literal("eglfs"))
- m_menuEnabled = false;
+ m_ui2Enabled = true;
+
+ const QByteArray dialogSet = qgetenv("QTWEBENGINE_DIALOG_SET");
+
+ if (!dialogSet.isEmpty()) {
+ if (dialogSet == QByteArrayLiteral("QtQuickControls2")) {
+ m_ui2Enabled = true;
+ } else if (dialogSet == QByteArrayLiteral("QtQuickControls1")
+ && m_ui2Enabled) {
+ m_ui2Enabled = false;
+ qWarning("QTWEBENGINE_DIALOG_SET=QtQuickControls1 forces use of Qt Quick Controls 1 "
+ "on an eglfs backend. This can crash your application!");
+ } else {
+ qWarning("Ignoring QTWEBENGINE_DIALOG_SET environment variable set to %s. Accepted "
+ "values are \"QtQuickControls1\" and \"QtQuickControls2\"", dialogSet.data());
+ }
+ }
+
#ifndef QT_NO_ACCESSIBILITY
QAccessible::installFactory(&webAccessibleFactory);
#endif // QT_NO_ACCESSIBILITY
@@ -189,7 +208,7 @@ UIDelegatesManager *QQuickWebEngineViewPrivate::ui()
{
Q_Q(QQuickWebEngineView);
if (m_uIDelegatesManager.isNull())
- m_uIDelegatesManager.reset(new UIDelegatesManager(q));
+ m_uIDelegatesManager.reset(m_ui2Enabled ? new UI2DelegatesManager(q) : new UIDelegatesManager(q));
return m_uIDelegatesManager.data();
}
@@ -216,31 +235,41 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
{
Q_Q(QQuickWebEngineView);
- if (!m_menuEnabled) {
- qWarning("You are trying to open context menu on eglfs backend, which is not currently supported\n"
- "See QTBUG-53467.");
- return false;
- }
+ m_contextMenuData = data;
+
+ QQuickWebEngineContextMenuRequest *request = new QQuickWebEngineContextMenuRequest(data);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(request);
+ Q_EMIT q->contextMenuRequested(request);
+
+ if (request->isAccepted())
+ return true;
// Assign the WebEngineView as the parent of the menu, so mouse events are properly propagated
// on OSX.
- QObject *menu = ui()->addMenu(q, QString(), data.pos);
+ QObject *menu = ui()->addMenu(q, QString(), data.position());
if (!menu)
return false;
- contextMenuData.update(data);
- Q_EMIT q->experimental()->contextMenuDataChanged();
-
// Populate our menu
MenuItemHandler *item = 0;
-
- if (!data.linkText.isEmpty() && data.linkUrl.isValid()) {
+ if (data.isEditable() && !data.spellCheckerSuggestions().isEmpty()) {
+ const QPointer<QQuickWebEngineView> qRef(q);
+ for (int i=0; i < data.spellCheckerSuggestions().count() && i < 4; i++) {
+ item = new MenuItemHandler(menu);
+ QString replacement = data.spellCheckerSuggestions().at(i);
+ QObject::connect(item, &MenuItemHandler::triggered, [qRef, replacement] { qRef->replaceMisspelledWord(replacement); });
+ ui()->addMenuItem(item, replacement);
+ }
+ ui()->addMenuSeparator(menu);
+ }
+ if (!data.linkText().isEmpty() && data.linkUrl().isValid()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::OpenLinkInThisWindow); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Follow Link"));
}
- if (data.selectedText.isEmpty()) {
+ if (data.selectedText().isEmpty()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::goBack);
ui()->addMenuItem(item, QQuickWebEngineView::tr("Back"), QStringLiteral("go-previous"), q->canGoBack());
@@ -252,6 +281,10 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::reload);
ui()->addMenuItem(item, QQuickWebEngineView::tr("Reload"), QStringLiteral("view-refresh"));
+
+ item = new MenuItemHandler(menu);
+ QObject::connect(item, &MenuItemHandler::triggered, q, &QQuickWebEngineView::viewSource);
+ ui()->addMenuItem(item, QQuickWebEngineView::tr("View Page Source"), QStringLiteral("view-source"), q->canViewSource());
} else {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::Copy); });
@@ -261,7 +294,7 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
ui()->addMenuItem(item, QQuickWebEngineView::tr("Unselect"));
}
- if (!contextMenuData.linkText().isEmpty() && contextMenuData.linkUrl().isValid()) {
+ if (!data.linkText().isEmpty() && data.linkUrl().isValid()) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyLinkToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Link URL"));
@@ -269,9 +302,9 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadLinkToDisk); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Link"));
}
- if (contextMenuData.mediaUrl().isValid()) {
- switch (contextMenuData.mediaType()) {
- case QQuickWebEngineContextMenuData::MediaTypeImage:
+ if (data.mediaUrl().isValid()) {
+ switch (data.mediaType()) {
+ case WebEngineContextMenuData::MediaTypeImage:
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyImageUrlToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Image URL"));
@@ -282,11 +315,11 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::DownloadImageToDisk); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Save Image"));
break;
- case QQuickWebEngineContextMenuData::MediaTypeCanvas:
+ case WebEngineContextMenuData::MediaTypeCanvas:
Q_UNREACHABLE(); // mediaUrl is invalid for canvases
break;
- case QQuickWebEngineContextMenuData::MediaTypeAudio:
- case QQuickWebEngineContextMenuData::MediaTypeVideo:
+ case WebEngineContextMenuData::MediaTypeAudio:
+ case WebEngineContextMenuData::MediaTypeVideo:
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyMediaUrlToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Media URL"));
@@ -299,12 +332,12 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaLoop); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Looping"));
- if (data.mediaFlags & WebEngineContextMenuData::MediaHasAudio) {
+ if (data.mediaFlags() & WebEngineContextMenuData::MediaHasAudio) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaMute); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Mute"));
}
- if (data.mediaFlags & WebEngineContextMenuData::MediaCanToggleControls) {
+ if (data.mediaFlags() & WebEngineContextMenuData::MediaCanToggleControls) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::ToggleMediaControls); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Toggle Media Controls"));
@@ -313,7 +346,7 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
default:
break;
}
- } else if (contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeCanvas) {
+ } else if (data.mediaType() == WebEngineContextMenuData::MediaTypeCanvas) {
item = new MenuItemHandler(menu);
QObject::connect(item, &MenuItemHandler::triggered, [q] { q->triggerWebAction(QQuickWebEngineView::CopyImageToClipboard); });
ui()->addMenuItem(item, QQuickWebEngineView::tr("Copy Image"));
@@ -341,7 +374,7 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
}
// Now fire the popup() method on the top level menu
- QMetaObject::invokeMethod(menu, "popup");
+ ui()->showMenu(menu);
return true;
}
@@ -356,7 +389,13 @@ void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const Q
void QQuickWebEngineViewPrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> dialog)
{
- ui()->showDialog(dialog);
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineJavaScriptDialogRequest *request = new QQuickWebEngineJavaScriptDialogRequest(dialog);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(request);
+ Q_EMIT q->javaScriptDialogRequested(request);
+ if (!request->isAccepted())
+ ui()->showDialog(dialog);
}
void QQuickWebEngineViewPrivate::allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController)
@@ -381,12 +420,24 @@ void QQuickWebEngineViewPrivate::runGeolocationPermissionRequest(const QUrl &url
void QQuickWebEngineViewPrivate::showColorDialog(QSharedPointer<ColorChooserController> controller)
{
- ui()->showColorDialog(controller);
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineColorDialogRequest *request = new QQuickWebEngineColorDialogRequest(controller);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(request);
+ Q_EMIT q->colorDialogRequested(request);
+ if (!request->isAccepted())
+ ui()->showColorDialog(controller);
}
-void QQuickWebEngineViewPrivate::runFileChooser(FilePickerController* controller)
+void QQuickWebEngineViewPrivate::runFileChooser(QSharedPointer<FilePickerController> controller)
{
- ui()->showFilePicker(controller);
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineFileDialogRequest *request = new QQuickWebEngineFileDialogRequest(controller);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(request);
+ Q_EMIT q->fileDialogRequested(request);
+ if (!request->isAccepted())
+ ui()->showFilePicker(controller);
}
void QQuickWebEngineViewPrivate::passOnFocus(bool reverse)
@@ -654,7 +705,13 @@ void QQuickWebEngineViewPrivate::javaScriptConsoleMessage(JavaScriptConsoleMessa
void QQuickWebEngineViewPrivate::authenticationRequired(QSharedPointer<AuthenticationDialogController> controller)
{
- ui()->showDialog(controller);
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineAuthenticationDialogRequest *request = new QQuickWebEngineAuthenticationDialogRequest(controller);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(request);
+ Q_EMIT q->authenticationDialogRequested(request);
+ if (!request->isAccepted())
+ ui()->showDialog(controller);
}
void QQuickWebEngineViewPrivate::runMediaAccessPermissionRequest(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags requestFlags)
@@ -1076,18 +1133,40 @@ void QQuickWebEngineViewPrivate::showValidationMessage(const QRect &anchor, cons
if (m_testSupport)
Q_EMIT m_testSupport->validationMessageShown(mainText, subText);
#endif
-
- ui()->showMessageBubble(anchor, mainText, subText);
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineFormValidationMessageRequest *request;
+ request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::RequestTypeShow,
+ anchor,mainText,subText);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(request);
+ Q_EMIT q->formValidationMessageRequested(request);
+ if (!request->isAccepted())
+ ui()->showMessageBubble(anchor, mainText, subText);
}
void QQuickWebEngineViewPrivate::hideValidationMessage()
{
- ui()->hideMessageBubble();
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineFormValidationMessageRequest *request;
+ request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::RequestTypeHide);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(request);
+ Q_EMIT q->formValidationMessageRequested(request);
+ if (!request->isAccepted())
+ ui()->hideMessageBubble();
}
void QQuickWebEngineViewPrivate::moveValidationMessage(const QRect &anchor)
{
- ui()->moveMessageBubble(anchor);
+ Q_Q(QQuickWebEngineView);
+ QQuickWebEngineFormValidationMessageRequest *request;
+ request = new QQuickWebEngineFormValidationMessageRequest(QQuickWebEngineFormValidationMessageRequest::RequestTypeMove,
+ anchor);
+ // mark the object for gc by creating temporary jsvalue
+ qmlEngine(q)->newQObject(request);
+ Q_EMIT q->formValidationMessageRequested(request);
+ if (!request->isAccepted())
+ ui()->moveMessageBubble(anchor);
}
void QQuickWebEngineViewPrivate::updateScrollPosition(const QPointF &position)
@@ -1123,6 +1202,11 @@ bool QQuickWebEngineViewPrivate::isEnabled() const
return q->isEnabled();
}
+void QQuickWebEngineViewPrivate::setToolTip(const QString &toolTipText)
+{
+ ui()->showToolTip(toolTipText);
+}
+
bool QQuickWebEngineView::isLoading() const
{
Q_D(const QQuickWebEngineView);
@@ -1272,6 +1356,24 @@ void QQuickWebEngineView::printToPdf(const QJSValue &callback, PrintedPageSizeId
d->m_callbacks.insert(requestId, callback);
}
+void QQuickWebEngineView::replaceMisspelledWord(const QString &replacement)
+{
+ Q_D(QQuickWebEngineView);
+ d->adapter->replaceMisspelling(replacement);
+}
+
+void QQuickWebEngineView::viewSource()
+{
+ Q_D(QQuickWebEngineView);
+ d->adapter->viewSource();
+}
+
+bool QQuickWebEngineView::canViewSource() const
+{
+ Q_D(const QQuickWebEngineView);
+ return d->adapter->canViewSource();
+}
+
bool QQuickWebEngineView::isFullScreen() const
{
Q_D(const QQuickWebEngineView);
@@ -1512,118 +1614,118 @@ void QQuickWebEngineView::triggerWebAction(WebAction action)
d->adapter->unselect();
break;
case OpenLinkInThisWindow:
- if (d->contextMenuData.linkUrl().isValid())
- setUrl(d->contextMenuData.linkUrl());
+ if (d->m_contextMenuData.linkUrl().isValid())
+ setUrl(d->m_contextMenuData.linkUrl());
break;
case OpenLinkInNewWindow:
- if (d->contextMenuData.linkUrl().isValid()) {
+ if (d->m_contextMenuData.linkUrl().isValid()) {
QQuickWebEngineNewViewRequest request;
- request.m_requestedUrl = d->contextMenuData.linkUrl();
+ request.m_requestedUrl = d->m_contextMenuData.linkUrl();
request.m_isUserInitiated = true;
request.m_destination = NewViewInWindow;
Q_EMIT newViewRequested(&request);
}
break;
case OpenLinkInNewTab:
- if (d->contextMenuData.linkUrl().isValid()) {
+ if (d->m_contextMenuData.linkUrl().isValid()) {
QQuickWebEngineNewViewRequest request;
- request.m_requestedUrl = d->contextMenuData.linkUrl();
+ request.m_requestedUrl = d->m_contextMenuData.linkUrl();
request.m_isUserInitiated = true;
request.m_destination = NewViewInBackgroundTab;
Q_EMIT newViewRequested(&request);
}
break;
case CopyLinkToClipboard:
- if (d->contextMenuData.linkUrl().isValid()) {
- QString urlString = d->contextMenuData.linkUrl().toString(QUrl::FullyEncoded);
- QString title = d->contextMenuData.linkText().toHtmlEscaped();
+ if (d->m_contextMenuData.linkUrl().isValid()) {
+ QString urlString = d->m_contextMenuData.linkUrl().toString(QUrl::FullyEncoded);
+ QString title = d->m_contextMenuData.linkText().toHtmlEscaped();
QMimeData *data = new QMimeData();
data->setText(urlString);
QString html = QStringLiteral("<a href=\"") + urlString + QStringLiteral("\">") + title + QStringLiteral("</a>");
data->setHtml(html);
- data->setUrls(QList<QUrl>() << d->contextMenuData.linkUrl());
+ data->setUrls(QList<QUrl>() << d->m_contextMenuData.linkUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case DownloadLinkToDisk:
- if (d->contextMenuData.linkUrl().isValid())
- d->adapter->download(d->contextMenuData.linkUrl(), d->contextMenuData.d->suggestedFileName);
+ if (d->m_contextMenuData.linkUrl().isValid())
+ d->adapter->download(d->m_contextMenuData.linkUrl(), d->m_contextMenuData.suggestedFileName());
break;
case CopyImageToClipboard:
- if (d->contextMenuData.d->hasImageContent &&
- (d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeImage ||
- d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeCanvas))
+ if (d->m_contextMenuData.hasImageContent() &&
+ (d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeImage ||
+ d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeCanvas))
{
- d->adapter->copyImageAt(d->contextMenuData.position());
+ d->adapter->copyImageAt(d->m_contextMenuData.position());
}
break;
case CopyImageUrlToClipboard:
- if (d->contextMenuData.mediaUrl().isValid() && d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeImage) {
- QString urlString = d->contextMenuData.mediaUrl().toString(QUrl::FullyEncoded);
- QString title = d->contextMenuData.linkText();
+ if (d->m_contextMenuData.mediaUrl().isValid() && d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeImage) {
+ QString urlString = d->m_contextMenuData.mediaUrl().toString(QUrl::FullyEncoded);
+ QString title = d->m_contextMenuData.linkText();
if (!title.isEmpty())
title = QStringLiteral(" alt=\"%1\"").arg(title.toHtmlEscaped());
QMimeData *data = new QMimeData();
data->setText(urlString);
QString html = QStringLiteral("<img src=\"") + urlString + QStringLiteral("\"") + title + QStringLiteral("></img>");
data->setHtml(html);
- data->setUrls(QList<QUrl>() << d->contextMenuData.mediaUrl());
+ data->setUrls(QList<QUrl>() << d->m_contextMenuData.mediaUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case DownloadImageToDisk:
case DownloadMediaToDisk:
- if (d->contextMenuData.mediaUrl().isValid())
- d->adapter->download(d->contextMenuData.mediaUrl(), d->contextMenuData.d->suggestedFileName);
+ if (d->m_contextMenuData.mediaUrl().isValid())
+ d->adapter->download(d->m_contextMenuData.mediaUrl(), d->m_contextMenuData.suggestedFileName());
break;
case CopyMediaUrlToClipboard:
- if (d->contextMenuData.mediaUrl().isValid() &&
- (d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeAudio ||
- d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeVideo))
+ if (d->m_contextMenuData.mediaUrl().isValid() &&
+ (d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio ||
+ d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo))
{
- QString urlString = d->contextMenuData.mediaUrl().toString(QUrl::FullyEncoded);
+ QString urlString = d->m_contextMenuData.mediaUrl().toString(QUrl::FullyEncoded);
QMimeData *data = new QMimeData();
data->setText(urlString);
- if (d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeAudio)
+ if (d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio)
data->setHtml(QStringLiteral("<audio src=\"") + urlString + QStringLiteral("\"></audio>"));
else
data->setHtml(QStringLiteral("<video src=\"") + urlString + QStringLiteral("\"></video>"));
- data->setUrls(QList<QUrl>() << d->contextMenuData.mediaUrl());
+ data->setUrls(QList<QUrl>() << d->m_contextMenuData.mediaUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case ToggleMediaControls:
- if (d->contextMenuData.mediaUrl().isValid() && d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaCanToggleControls) {
- bool enable = !(d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaControls);
- d->adapter->executeMediaPlayerActionAt(d->contextMenuData.position(), WebContentsAdapter::MediaPlayerControls, enable);
+ if (d->m_contextMenuData.mediaUrl().isValid() && d->m_contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaCanToggleControls) {
+ bool enable = !(d->m_contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaControls);
+ d->adapter->executeMediaPlayerActionAt(d->m_contextMenuData.position(), WebContentsAdapter::MediaPlayerControls, enable);
}
break;
case ToggleMediaLoop:
- if (d->contextMenuData.mediaUrl().isValid() &&
- (d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeAudio ||
- d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeVideo))
+ if (d->m_contextMenuData.mediaUrl().isValid() &&
+ (d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio ||
+ d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo))
{
- bool enable = !(d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaLoop);
- d->adapter->executeMediaPlayerActionAt(d->contextMenuData.position(), WebContentsAdapter::MediaPlayerLoop, enable);
+ bool enable = !(d->m_contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaLoop);
+ d->adapter->executeMediaPlayerActionAt(d->m_contextMenuData.position(), WebContentsAdapter::MediaPlayerLoop, enable);
}
break;
case ToggleMediaPlayPause:
- if (d->contextMenuData.mediaUrl().isValid() &&
- (d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeAudio ||
- d->contextMenuData.mediaType() == QQuickWebEngineContextMenuData::MediaTypeVideo))
+ if (d->m_contextMenuData.mediaUrl().isValid() &&
+ (d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio ||
+ d->m_contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo))
{
- bool enable = (d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaPaused);
- d->adapter->executeMediaPlayerActionAt(d->contextMenuData.position(), WebContentsAdapter::MediaPlayerPlay, enable);
+ bool enable = (d->m_contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaPaused);
+ d->adapter->executeMediaPlayerActionAt(d->m_contextMenuData.position(), WebContentsAdapter::MediaPlayerPlay, enable);
}
break;
case ToggleMediaMute:
- if (d->contextMenuData.mediaUrl().isValid() && d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaHasAudio) {
- bool enable = !(d->contextMenuData.d->mediaFlags & WebEngineContextMenuData::MediaMuted);
- d->adapter->executeMediaPlayerActionAt(d->contextMenuData.position(), WebContentsAdapter::MediaPlayerMute, enable);
+ if (d->m_contextMenuData.mediaUrl().isValid() && d->m_contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaHasAudio) {
+ bool enable = !(d->m_contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaMuted);
+ d->adapter->executeMediaPlayerActionAt(d->m_contextMenuData.position(), WebContentsAdapter::MediaPlayerMute, enable);
}
break;
case InspectElement:
- d->adapter->inspectElementAt(d->contextMenuData.position());
+ d->adapter->inspectElementAt(d->m_contextMenuData.position());
break;
case ExitFullScreen:
d->adapter->exitFullScreen();
@@ -1639,12 +1741,6 @@ void QQuickWebEngineView::triggerWebAction(WebAction action)
}
}
-const QQuickWebEngineContextMenuData *QQuickWebEngineViewExperimental::contextMenuData() const
-{
- Q_D(const QQuickWebEngineView);
- return &d->contextMenuData;
-}
-
QSizeF QQuickWebEngineView::contentsSize() const
{
Q_D(const QQuickWebEngineView);
diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h
index b9555d2d9..1d44a48dd 100644
--- a/src/webengine/api/qquickwebengineview_p.h
+++ b/src/webengine/api/qquickwebengineview_p.h
@@ -59,15 +59,20 @@
QT_BEGIN_NAMESPACE
class QQmlWebChannel;
+class QQuickWebEngineAuthenticationDialogRequest;
class QQuickWebEngineCertificateError;
-class QQuickWebEngineContextMenuData;
+class QQuickWebEngineColorDialogRequest;
+class QQuickWebEngineContextMenuRequest;
class QQuickWebEngineFaviconProvider;
+class QQuickWebEngineFileDialogRequest;
class QQuickWebEngineHistory;
+class QQuickWebEngineJavaScriptDialogRequest;
class QQuickWebEngineLoadRequest;
class QQuickWebEngineNavigationRequest;
class QQuickWebEngineNewViewRequest;
class QQuickWebEngineProfile;
class QQuickWebEngineSettings;
+class QQuickWebEngineFormValidationMessageRequest;
class QQuickWebEngineViewExperimental;
class QQuickWebEngineViewPrivate;
@@ -94,7 +99,7 @@ private:
const bool m_toggleOn;
};
-#define LATEST_WEBENGINEVIEW_REVISION 3
+#define LATEST_WEBENGINEVIEW_REVISION 4
class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem {
Q_OBJECT
@@ -119,6 +124,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem {
Q_PROPERTY(bool audioMuted READ isAudioMuted WRITE setAudioMuted NOTIFY audioMutedChanged FINAL REVISION 3)
Q_PROPERTY(bool recentlyAudible READ recentlyAudible NOTIFY recentlyAudibleChanged FINAL REVISION 3)
Q_PROPERTY(uint webChannelWorld READ webChannelWorld WRITE setWebChannelWorld NOTIFY webChannelWorldChanged REVISION 3)
+ Q_PROPERTY(bool canViewSource READ canViewSource FINAL REVISION 4)
#ifdef ENABLE_QML_TESTSUPPORT_API
Q_PROPERTY(QQuickWebEngineTestSupport *testSupport READ testSupport WRITE setTestSupport FINAL)
@@ -145,6 +151,7 @@ public:
void setBackgroundColor(const QColor &color);
QSizeF contentsSize() const;
QPointF scrollPosition() const;
+ bool canViewSource() const;
QQuickWebEngineViewExperimental *experimental() const;
@@ -472,6 +479,9 @@ public Q_SLOTS:
Q_REVISION(2) void triggerWebAction(WebAction action);
Q_REVISION(3) void printToPdf(const QString &filePath, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait);
Q_REVISION(3) void printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait);
+ Q_REVISION(4) void replaceMisspelledWord(const QString &replacement);
+ Q_REVISION(4) void viewSource();
+
private Q_SLOTS:
void lazyInitialize();
@@ -501,6 +511,12 @@ Q_SIGNALS:
Q_REVISION(3) void audioMutedChanged(bool muted);
Q_REVISION(3) void recentlyAudibleChanged(bool recentlyAudible);
Q_REVISION(3) void webChannelWorldChanged(uint);
+ Q_REVISION(4) void contextMenuRequested(QQuickWebEngineContextMenuRequest *request);
+ Q_REVISION(4) void authenticationDialogRequested(QQuickWebEngineAuthenticationDialogRequest *request);
+ Q_REVISION(4) void javaScriptDialogRequested(QQuickWebEngineJavaScriptDialogRequest *request);
+ Q_REVISION(4) void colorDialogRequested(QQuickWebEngineColorDialogRequest *request);
+ Q_REVISION(4) void fileDialogRequested(QQuickWebEngineFileDialogRequest *request);
+ Q_REVISION(4) void formValidationMessageRequested(QQuickWebEngineFormValidationMessageRequest *request);
protected:
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 769e41a44..c6ff18373 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -52,7 +52,6 @@
//
#include "qquickwebengineview_p.h"
-#include "qquickwebenginecontextmenudata_p.h"
#include "web_contents_adapter_client.h"
#include <QScopedPointer>
@@ -70,6 +69,7 @@ QT_BEGIN_NAMESPACE
class QQuickWebEngineView;
class QQmlComponent;
class QQmlContext;
+class QQuickWebEngineContextMenuRequest;
class QQuickWebEngineSettings;
class QQuickWebEngineFaviconProvider;
@@ -101,17 +101,13 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineViewExperimental : public QObjec
Q_OBJECT
Q_PROPERTY(QQuickWebEngineViewport *viewport READ viewport)
Q_PROPERTY(QQmlComponent *extraContextMenuEntriesComponent READ extraContextMenuEntriesComponent WRITE setExtraContextMenuEntriesComponent NOTIFY extraContextMenuEntriesComponentChanged)
- Q_PROPERTY(const QQuickWebEngineContextMenuData *contextMenuData READ contextMenuData NOTIFY contextMenuDataChanged)
QQuickWebEngineViewport *viewport() const;
void setExtraContextMenuEntriesComponent(QQmlComponent *);
QQmlComponent *extraContextMenuEntriesComponent() const;
- const QQuickWebEngineContextMenuData *contextMenuData() const;
-
Q_SIGNALS:
void extraContextMenuEntriesComponentChanged();
- void contextMenuDataChanged();
private:
QQuickWebEngineViewExperimental(QQuickWebEngineViewPrivate* viewPrivate);
@@ -161,13 +157,16 @@ public:
virtual bool contextMenuRequested(const QtWebEngineCore::WebEngineContextMenuData &) Q_DECL_OVERRIDE;
virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) Q_DECL_OVERRIDE;
virtual void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) Q_DECL_OVERRIDE;
- virtual void runFileChooser(QtWebEngineCore::FilePickerController *controller) Q_DECL_OVERRIDE;
+ virtual void runFileChooser(QSharedPointer<QtWebEngineCore::FilePickerController>) Q_DECL_OVERRIDE;
virtual void showColorDialog(QSharedPointer<QtWebEngineCore::ColorChooserController>) Q_DECL_OVERRIDE;
virtual void didRunJavaScript(quint64, const QVariant&) Q_DECL_OVERRIDE;
virtual void didFetchDocumentMarkup(quint64, const QString&) Q_DECL_OVERRIDE { }
virtual void didFetchDocumentInnerText(quint64, const QString&) Q_DECL_OVERRIDE { }
virtual void didFindText(quint64, int) Q_DECL_OVERRIDE;
virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE;
+#if !defined(QT_NO_WIDGETS) && !defined(QT_NO_PRINTER)
+ virtual void didPrintPageOnPrinter(quint64, bool) Q_DECL_OVERRIDE { }
+#endif
virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE;
virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE;
virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE;
@@ -190,6 +189,7 @@ public:
void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions,
const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE;
virtual bool isEnabled() const Q_DECL_OVERRIDE;
+ virtual void setToolTip(const QString &toolTipText) Q_DECL_OVERRIDE;
const QObject *holdingQObject() const Q_DECL_OVERRIDE;
virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE;
@@ -217,7 +217,7 @@ public:
QQuickWebEngineTestSupport *m_testSupport;
#endif
QQmlComponent *contextMenuExtraItems;
- QQuickWebEngineContextMenuData contextMenuData;
+ QtWebEngineCore::WebEngineContextMenuData m_contextMenuData;
QUrl explicitUrl;
QUrl iconUrl;
QQuickWebEngineFaviconProvider *faviconProvider;
@@ -225,6 +225,7 @@ public:
bool m_fullscreenMode;
bool isLoading;
bool m_activeFocusOnPress;
+ bool m_navigationActionTriggered;
qreal devicePixelRatio;
QMap<quint64, QJSValue> m_callbacks;
QList<QSharedPointer<CertificateErrorController> > m_certificateErrorControllers;
@@ -237,8 +238,7 @@ private:
qreal m_dpiScale;
QColor m_backgroundColor;
qreal m_defaultZoomFactor;
- // QTBUG-53467
- bool m_menuEnabled;
+ bool m_ui2Enabled;
};
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/webengine/doc/qtwebengine.qdocconf b/src/webengine/doc/qtwebengine.qdocconf
index 009902080..d9b1f1154 100644
--- a/src/webengine/doc/qtwebengine.qdocconf
+++ b/src/webengine/doc/qtwebengine.qdocconf
@@ -47,6 +47,7 @@ depends += qtcore \
qtqml \
qtquick \
qtquickcontrols \
+ qtquickcontrols2 \
qtdoc \
qtwebchannel \
qtwebview \
@@ -66,6 +67,7 @@ exampledirs += . \
../../core/doc/snippets \
../../webenginewidgets/doc/snippets
+examples.fileextensions += *.aff *.dic
imagedirs += images
diff --git a/src/webengine/doc/src/external-resources.qdoc b/src/webengine/doc/src/external-resources.qdoc
index c4cfe24af..ced64dff7 100644
--- a/src/webengine/doc/src/external-resources.qdoc
+++ b/src/webengine/doc/src/external-resources.qdoc
@@ -90,6 +90,11 @@
\title Shaka Player
*/
+/*!
+ \externalpage https://sourceforge.net/projects/hunspell/
+ \title Hunspell Project
+*/
+
/*
This prevents autolinking of each occurrence of 'WebEngine'
To link to the WebEngine QML type, use explicit linking:
@@ -101,3 +106,18 @@
\title WebEngine
\internal
*/
+
+/*!
+ \externalpage https://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1
+ \title RFC 2616 section 19.5.1
+*/
+
+/*!
+ \externalpage http://www.w3schools.com/tags/att_a_download.asp
+ \title HTML download Attribute
+*/
+
+/*!
+ \externalpage https://www.iana.org/assignments/uri-schemes/prov/view-source
+ \title view-source URI scheme
+*/
diff --git a/src/webengine/doc/src/qtwebengine-features.qdoc b/src/webengine/doc/src/qtwebengine-features.qdoc
index 52f7da928..48f1536b4 100644
--- a/src/webengine/doc/src/qtwebengine-features.qdoc
+++ b/src/webengine/doc/src/qtwebengine-features.qdoc
@@ -31,7 +31,7 @@
\brief Summarizes Qt WebEngine features.
- Qt WebEngine supports the following Chromium features:
+ Qt WebEngine supports the following features:
\list
\li \l{Audio and Video Codecs}
@@ -40,8 +40,11 @@
\li \l{Fullscreen}
\li \l{HTML5 DRM}
\li \l{HTML5 Geolocation}
+ \li \l{Native Dialogs}
\li \l{Pepper Plugin API}
\li \l{Print to PDF}
+ \li \l{Spellchecker}
+ \li \l{View Source}
\li \l{WebRTC}
\endlist
@@ -140,6 +143,40 @@
Support for this feature was added in Qt 5.5.0.
+ \section1 Native Dialogs
+
+ A web page might request dialogs for the following functions:
+
+ \list
+ \li Entering user credentials for HTTP and proxy authentication
+ \li Displaying JavaScript alerts, confirmation dialogs, and prompts
+ \li Picking colors
+ \li Selecting files
+ \li Displaying form validation messages
+ \endlist
+
+ Qt WebEngine provides standard dialogs for these functions. In widget-based
+ applications, the standard dialogs are based on QDialog, whereas in Qt Quick
+ applications, they can be based either on Qt Quick Controls 1 or Qt Quick
+ Controls 2 (since Qt 5.8). The latter are used only on \c eglfs platforms.
+
+ To explicitly force either dialogs based on Qt Quick Controls 1 or Qt Quick
+ Controls 2, set the \c QTWEBENGINE_DIALOG_SET environment variable to either
+ \c{QtQuickControls1} or \c{QtQuickControls2}.
+
+ Qt WebEngine Widgets dialogs can be customized by reimplementing the
+ QWebEnginePage::chooseFiles(), QWebEnginePage::javaScriptAlert(),
+ QWebEnginePage::javaScriptConfirm(), and QWebEnginePage::javaScriptPrompt()
+ functions.
+
+ Since Qt 5.8, Qt Quick dialogs can be customized by connecting to the
+ WebEngineView::authenticationDialogRequested(),
+ WebEngineView::javaScriptDialogRequested(),
+ WebEngineView::colorDialogRequested(),
+ WebEngineView::fileDialogRequested(), and
+ WebEngineView::formValidationMessageRequested() signals. For an example,
+ see \l{WebEngine Qt Quick Custom Dialogs Example}.
+
\section1 Pepper Plugin API
Qt WebEngine supports loading Pepper Plugin API (PPAPI) plugins if
@@ -222,6 +259,77 @@
Support for this feature was added in Qt 5.7.0.
+ \section1 Spellchecker
+
+ Qt WebEngine supports integrating spellchecking support into HTML forms to
+ enable users to submit spellchecked messages. When the user clicks on
+ an underlined misspelled word, the default context menu displays up to four
+ suggestions. Selecting one will replace the misspelled word.
+
+ To be able to check the spelling, the spellchecker needs dictionaries. It
+ supports dictionaries from the \l{Hunspell project}, but they have to be
+ compiled into a special binary format. A Hunspell dictionary consists of two
+ files:
+
+ \list
+
+ \li A \c .dic file that is a dictionary containing words for the
+ language
+ \li An \c .aff file that defines the meaning of special flags in the
+ dictionary
+ \endlist
+
+ These two files can be converted into the \c bdic format by using the
+ \c qwebengine_convert_dict tool that is shipped together with Qt.
+ When the Qt WebEngine spellchecker initializes, it will try to load the
+ \c bdict dictionaries and to check them for consistency. First, it searches
+ \e qtwebengine_dictionaries directories relative to the executable,
+ then it will look in \c QT_INSTALL_PREFIX/qtwebengines_dictionaries.
+
+ Spellchecking is disabled by default and can be enabled per profile by
+ using the QWebEngineProfile::setSpellCheckEnabled() method in widget-based
+ applications and the \l {QQuickWebEngineProfile::spellCheckEnabled}
+ {WebEngineProfile.spellCheckEnabled} property in Qt Quick applications.
+
+ The current language used for spellchecking is defined per profile, and can
+ be set using the QWebEngineProfile::setSpellCheckLanguage() method or the
+ \l {QQuickWebEngineProfile::spellCheckLanguage}
+ {WebEngineProfile.spellCheckLanguage} property.
+
+ This feature can be tested by building and running the
+ \l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}.
+
+ Support for this feature was added in Qt 5.8.0.
+
+ \section1 View Source
+
+ Qt WebEngine supports viewing the HTML source of a web page.
+
+ This feature can be used from custom menus or assigned to custom events.
+ For more information, see WebEngineView::viewSource, WebEngineView::canViewSource,
+ QWebEnginePage::viewSource, and QWebEnginePage::canViewSource.
+
+ This feature can be tested by opening a web page in \l{WebEngine Widgets
+ Simple Browser Example}{Simple Browser} or \l{WebEngine Quick Nano Browser}
+ {Nano Browser}, and then selecting \c{Page Source} in the context menu. The
+ \c{Page Source} context menu entry opens the source view in a new tab.
+
+ For opening the source view in the current tab, URLs with \l{view-source URI scheme}
+ are also supported. For example, you can type the following URL to the URL bar
+ to view the HTML source of the qt.io web page:
+ \code
+ view-source:https://www.qt.io/
+ \endcode
+
+ Auto-completion of incomplete URLs with \l{view-source URI scheme} makes the usage of
+ this feature more comfortable. For example, the following incomplete URL also loads
+ the source view of the qt.io web page:
+ \code
+ view-source:qt.io
+ \endcode
+
+ Support for this feature was added in Qt 5.8.0.
+
\section1 WebRTC
WebRTC provides browsers with Real-Time Communications (RTC) capabilities
diff --git a/src/webengine/doc/src/qtwebengine-overview.qdoc b/src/webengine/doc/src/qtwebengine-overview.qdoc
index 6b5ccaa14..d7c8ab630 100644
--- a/src/webengine/doc/src/qtwebengine-overview.qdoc
+++ b/src/webengine/doc/src/qtwebengine-overview.qdoc
@@ -181,7 +181,8 @@
script to run, the injection point, and the world where the script is run. This enables
accessing the DOM to manipulate it within a world.
- \note Chromium extensions, such as \c @include, \c @match, and \c @exclude, are not supported.
+ The following Chromium extensions are supported since Qt 5.8: \c @exclude, \c @include,
+ \c @name, \c @match, and \c @run-at.
\section1 Managing Certificates
diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
index f16258354..9a59f1f1f 100644
--- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
+++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc
@@ -104,8 +104,8 @@
On OS X, the following are required:
\list
- \li OS X 10.9 or later
- \li Xcode 6.1 or later
+ \li OS X 10.10 or later
+ \li Xcode 6.3 or later
\li OS X 10.10 SDK or later
\endlist
diff --git a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
index 8549e7664..c67851a2a 100644
--- a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
+++ b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
@@ -24,7 +24,7 @@
*/
/*!
- \qmlmodule QtWebEngine 1.3
+ \qmlmodule QtWebEngine 1.4
\title Qt WebEngine QML Types
\brief Provides QML types for rendering web content within a QML application
\ingroup qtwebengine-modules
@@ -34,7 +34,7 @@
your .qml file:
\badcode
- import QtWebEngine 1.3
+ import QtWebEngine 1.4
\endcode
To link against the module, add the following QT variable to your qmake .pro
diff --git a/src/webengine/doc/src/webengineview.qdoc b/src/webengine/doc/src/webengineview.qdoc
index b72e405a8..82fd66989 100644
--- a/src/webengine/doc/src/webengineview.qdoc
+++ b/src/webengine/doc/src/webengineview.qdoc
@@ -82,7 +82,11 @@
described by \l FindFlags.
The \l setActiveFocusOnPress() method can be used to create a UI element that should not get
- focus. This can be useful in a hybrid UI.
+ focus on press. This can be useful in a hybrid UI.
+
+ The \l {WebEngineSettings::focusOnNavigationEnabled} {focusOnNavigationEnabled} setting can be
+ used to stop the view from automatically receiving focus when a navigation operation occurs
+ (like loading or reloading a page or navigating through history).
The \l linkHovered() signal is emitted when a mouse pointer passes over a link and thus
corresponds to the \c{mouseover} DOM event.
@@ -481,7 +485,7 @@
a web engine view can be used to create a UI element that should not get focus. This can be
useful in a hybrid UI.
- \sa activeFocusOnPressChanged()
+ \sa activeFocusOnPressChanged, WebEngineSettings::focusOnNavigationEnabled
*/
/*!
@@ -1139,3 +1143,104 @@
Also if the audio is paused, this signal is emitted with an approximate \b{2 second
delay}, from the moment the audio is paused.
*/
+
+/*!
+ \qmlmethod void WebEngineView::viewSource()
+ \since QtWebEngine 1.4
+
+ Shows the source of the current page in a new tab.
+
+ \sa canViewSource
+*/
+
+/*!
+ \qmlproperty bool WebEngineView::canViewSource
+ \brief This property holds whether the source for the current page can be viewed.
+ \since QtWebEngine 1.4
+
+ \sa viewSource()
+*/
+
+/*!
+ \qmlsignal WebEngineView::authenticationDialogRequested(AuthenticationDialogRequest request)
+ \since QtWebEngine 1.4
+
+ This signal is emitted when an authentication dialog is requested.
+
+ The request can be handled by using the methods of the AuthenticationDialogRequest
+ type.
+
+ \note Signal handlers need to call \c{request.accepted = true} to prevent a
+ default dialog from showing up. Make sure to call either
+ AuthenticationDialogRequest::dialogAccept() or AuthenticationDialogRequest::dialogReject()
+ afterwards.
+*/
+
+/*!
+ \qmlsignal WebEngineView::javaScriptDialogRequested(JavaScriptDialogRequest request)
+ \since QtWebEngine 1.4
+
+ This signal is emitted when a JavaScript dialog is requested.
+
+ The request can be handled by using the methods of the JavaScriptDialogRequest
+ type.
+
+ \note Signal handlers need to call \c{request.accepted = true} to prevent a
+ default dialog from showing up. Make sure to call either
+ JavaScriptDialogRequest::dialogAccept() or JavaScriptDialogRequest::dialogReject()
+ afterwards.
+*/
+
+/*!
+ \qmlsignal WebEngineView::colorDialogRequested(ColorDialogRequest request)
+ \since QtWebEngine 1.4
+
+ This signal is emitted when a color picker dialog is requested.
+
+ The request can be handled by using the methods of the ColorDialogRequest
+ type.
+
+ \note Signal handlers need to call \c{request.accepted = true} to prevent a
+ default dialog from showing up. Make sure to call either
+ ColorDialogRequest::dialogAccept() or ColorDialogRequest::dialogReject() afterwards.
+*/
+
+/*!
+ \qmlsignal WebEngineView::fileDialogRequested(FileDialogRequest request)
+ \since QtWebEngine 1.4
+
+ This signal is emitted when a file picker dialog is requested.
+
+ The request error can be handled by using the methods of the FileDialogRequest
+ type.
+
+ \note Signal handlers need to call \c{request.accepted = true} to prevent a
+ default dialog from showing up. Make sure to call either FileDialogRequest::dialogAccept()
+ or FileDialogRequest::dialogReject() afterwards.
+*/
+
+/*!
+ \qmlsignal WebEngineView::formValidationMessageRequested(FormValidationMessageRequest request)
+ \since QtWebEngine 1.4
+
+ This signal is emitted when a validation message is requested.
+
+ The request can be handled by using the methods of the FormValidationMessageRequest
+ type.
+
+ \note Signal handlers need to call \c{request.accepted = true} to prevent a
+ default dialog from showing up.
+*/
+
+/*!
+ \qmlsignal WebEngineView::contextMenuRequested(ContextMenuRequest request)
+ \since QtWebEngine 1.4
+
+ This signal is emitted when a context menu is requested.
+
+ The request can be handled by using the properties of the ContextMenuRequest
+ type.
+
+ \note Signal handlers need to call \c{request.accepted = true} to prevent a
+ default context menu from showing up.
+*/
diff --git a/src/webengine/plugin/experimental/plugin.cpp b/src/webengine/plugin/experimental/plugin.cpp
index c45bcee43..d9043f6d3 100644
--- a/src/webengine/plugin/experimental/plugin.cpp
+++ b/src/webengine/plugin/experimental/plugin.cpp
@@ -41,7 +41,6 @@
#include "qquickwebengineview_p.h"
#include "qquickwebengineview_p_p.h"
-#include "qquickwebenginecontextmenudata_p.h"
QT_BEGIN_NAMESPACE
@@ -56,7 +55,7 @@ public:
class QtWebEngineExperimentalPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
virtual void registerTypes(const char *uri)
{
@@ -70,11 +69,8 @@ public:
tr("Cannot create a separate instance of WebEngineViewExperimental"));
qmlRegisterUncreatableType<QQuickWebEngineViewport>(uri, 1, 0, "WebEngineViewport",
tr("Cannot create a separate instance of WebEngineViewport"));
- qmlRegisterUncreatableType<const QQuickWebEngineContextMenuData>(uri, 1, 0, "WebEngineContextMenuData",
- tr("Cannot create a separate instance of WebEngineContextMenuData"));
-
// Use the latest revision of QQuickWebEngineView when importing QtWebEngine.experimental 1.0
- qmlRegisterRevision<QQuickWebEngineView, LATEST_WEBENGINEVIEW_REVISION>(uri, 1, 0);
+ qmlRegisterRevision<QQuickWebEngineView, LATEST_WEBENGINEVIEW_REVISION>(uri, 1, 1);
}
};
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index b71689a34..e9312a92a 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -41,6 +41,8 @@
#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"
@@ -62,7 +64,7 @@ static QObject *webEngineSingletonProvider(QQmlEngine *, QJSEngine *)
class QtWebEnginePlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
virtual void initializeEngine(QQmlEngine *engine, const char *uri)
{
@@ -81,9 +83,11 @@ public:
qmlRegisterType<QQuickWebEngineView, 1>(uri, 1, 1, "WebEngineView");
qmlRegisterType<QQuickWebEngineView, 2>(uri, 1, 2, "WebEngineView");
qmlRegisterType<QQuickWebEngineView, 3>(uri, 1, 3, "WebEngineView");
+ qmlRegisterType<QQuickWebEngineView, 4>(uri, 1, 4, "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<QQuickWebEngineScript>(uri, 1, 1, "WebEngineScript");
qmlRegisterUncreatableType<QQuickWebEngineCertificateError>(uri, 1, 1, "WebEngineCertificateError", tr("Cannot create separate instance of WebEngineCertificateError"));
qmlRegisterUncreatableType<QQuickWebEngineDownloadItem>(uri, 1, 1, "WebEngineDownloadItem",
@@ -92,10 +96,13 @@ public:
tr("Cannot create a separate instance of WebEngineDownloadItem"));
qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 2>(uri, 1, 3, "WebEngineDownloadItem",
tr("Cannot create a separate instance of WebEngineDownloadItem"));
+ qmlRegisterUncreatableType<QQuickWebEngineDownloadItem, 3>(uri, 1, 4, "WebEngineDownloadItem",
+ tr("Cannot create a separate instance of WebEngineDownloadItem"));
qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 1, "WebEngineNewViewRequest", tr("Cannot create separate instance of WebEngineNewViewRequest"));
qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 1, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
qmlRegisterUncreatableType<QQuickWebEngineSettings, 1>(uri, 1, 2, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
qmlRegisterUncreatableType<QQuickWebEngineSettings, 2>(uri, 1, 3, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
+ qmlRegisterUncreatableType<QQuickWebEngineSettings, 3>(uri, 1, 4, "WebEngineSettings", tr("Cannot create a separate instance of WebEngineSettings"));
qmlRegisterSingletonType<QQuickWebEngineSingleton>(uri, 1, 1, "WebEngine", webEngineSingletonProvider);
qmlRegisterUncreatableType<QQuickWebEngineHistory>(uri, 1, 1, "NavigationHistory",
tr("Cannot create a separate instance of NavigationHistory"));
@@ -104,6 +111,19 @@ public:
qmlRegisterUncreatableType<QQuickWebEngineFullScreenRequest>(uri, 1, 1, "FullScreenRequest",
tr("Cannot create a separate instance of FullScreenRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineContextMenuRequest>(uri, 1, 4, "ContextMenuRequest",
+ tr("Cannot create separate instance of ContextMenuRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineAuthenticationDialogRequest>(uri, 1, 4, "AuthenticationDialogRequest",
+ tr("Cannot create separate instance of AuthenticationDialogRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineJavaScriptDialogRequest>(uri, 1, 4, "JavaScriptDialogRequest",
+ tr("Cannot create separate instance of JavaScriptDialogRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineColorDialogRequest>(uri, 1, 4, "ColorDialogRequest",
+ tr("Cannot create separate instance of ColorDialogRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineFileDialogRequest>(uri, 1, 4, "FileDialogRequest",
+ tr("Cannot create separate instance of FileDialogRequest"));
+ qmlRegisterUncreatableType<QQuickWebEngineFormValidationMessageRequest>(uri, 1, 4, "FormValidationMessageRequest",
+ tr("Cannot create separate instance of FormValidationMessageRequest"));
+
// For now (1.x import), the latest revision matches the minor version of the import.
qmlRegisterRevision<QQuickWebEngineView, LATEST_WEBENGINEVIEW_REVISION>(uri, 1, LATEST_WEBENGINEVIEW_REVISION);
}
diff --git a/src/webengine/plugin/plugin.pro b/src/webengine/plugin/plugin.pro
index 2fbadfc97..56eb7bd3c 100644
--- a/src/webengine/plugin/plugin.pro
+++ b/src/webengine/plugin/plugin.pro
@@ -1,7 +1,7 @@
CXX_MODULE = qml
TARGET = qtwebengineplugin
TARGETPATH = QtWebEngine
-IMPORT_VERSION = 1.3
+IMPORT_VERSION = 1.4
QT += webengine qml quick
QT_PRIVATE += webengine-private
diff --git a/src/webengine/plugin/testsupport/plugin.cpp b/src/webengine/plugin/testsupport/plugin.cpp
index e1252361e..9352e3666 100644
--- a/src/webengine/plugin/testsupport/plugin.cpp
+++ b/src/webengine/plugin/testsupport/plugin.cpp
@@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE
class QtWebEngineTestSupportPlugin : public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
virtual void registerTypes(const char *uri)
{
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
index 80bf0b49a..68b097d4a 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
+++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
@@ -50,6 +50,11 @@
#include <private/qquickwindow_p.h>
#include <private/qsgcontext_p.h>
+#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0))
+#include <QSGSimpleRectNode>
+#include <QSGSimpleTextureNode>
+#endif
+
namespace QtWebEngineCore {
RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(RenderWidgetHostViewQtDelegateClient *client, bool isPopup)
@@ -177,10 +182,33 @@ QSGLayer *RenderWidgetHostViewQtDelegateQuick::createLayer()
return renderContext->sceneGraphContext()->createLayer(renderContext);
}
-QSGImageNode *RenderWidgetHostViewQtDelegateQuick::createImageNode()
+QSGInternalImageNode *RenderWidgetHostViewQtDelegateQuick::createImageNode()
{
QSGRenderContext *renderContext = QQuickWindowPrivate::get(QQuickItem::window())->context;
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
+ return renderContext->sceneGraphContext()->createInternalImageNode();
+#else
return renderContext->sceneGraphContext()->createImageNode();
+#endif
+}
+
+QSGTextureNode *RenderWidgetHostViewQtDelegateQuick::createTextureNode()
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
+ return QQuickItem::window()->createImageNode();
+#else
+ return new QSGSimpleTextureNode();
+#endif
+}
+
+QSGRectangleNode *RenderWidgetHostViewQtDelegateQuick::createRectangleNode()
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
+ return QQuickItem::window()->createRectangleNode();
+#else
+ QSGRenderContext *renderContext = QQuickWindowPrivate::get(QQuickItem::window())->context;
+ return renderContext->sceneGraphContext()->createRectangleNode();
+#endif
}
void RenderWidgetHostViewQtDelegateQuick::update()
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.h b/src/webengine/render_widget_host_view_qt_delegate_quick.h
index c51ca3408..de3aff291 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quick.h
+++ b/src/webengine/render_widget_host_view_qt_delegate_quick.h
@@ -66,13 +66,14 @@ public:
virtual QWindow* window() const Q_DECL_OVERRIDE;
virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE;
virtual QSGLayer *createLayer() Q_DECL_OVERRIDE;
- virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE;
+ virtual QSGInternalImageNode *createImageNode() Q_DECL_OVERRIDE;
+ virtual QSGTextureNode *createTextureNode() Q_DECL_OVERRIDE;
+ virtual QSGRectangleNode *createRectangleNode() Q_DECL_OVERRIDE;
virtual void update() Q_DECL_OVERRIDE;
virtual void updateCursor(const QCursor &) Q_DECL_OVERRIDE;
virtual void resize(int width, int height) Q_DECL_OVERRIDE;
virtual void move(const QPoint&) Q_DECL_OVERRIDE { }
virtual void inputMethodStateChanged(bool editorVisible) Q_DECL_OVERRIDE;
- virtual void setTooltip(const QString&) Q_DECL_OVERRIDE { }
// The QtQuick view doesn't have a backbuffer of its own and doesn't need this
virtual void setClearColor(const QColor &) Q_DECL_OVERRIDE { }
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp
index 64839c9fa..7b7d32d67 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp
+++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp
@@ -111,11 +111,21 @@ QSGLayer *RenderWidgetHostViewQtDelegateQuickWindow::createLayer()
return m_realDelegate->createLayer();
}
-QSGImageNode *RenderWidgetHostViewQtDelegateQuickWindow::createImageNode()
+QSGInternalImageNode *RenderWidgetHostViewQtDelegateQuickWindow::createImageNode()
{
return m_realDelegate->createImageNode();
}
+QSGTextureNode *RenderWidgetHostViewQtDelegateQuickWindow::createTextureNode()
+{
+ return m_realDelegate->createTextureNode();
+}
+
+QSGRectangleNode *RenderWidgetHostViewQtDelegateQuickWindow::createRectangleNode()
+{
+ return m_realDelegate->createRectangleNode();
+}
+
void RenderWidgetHostViewQtDelegateQuickWindow::update()
{
QQuickWindow::update();
@@ -138,9 +148,4 @@ void RenderWidgetHostViewQtDelegateQuickWindow::move(const QPoint &screenPos)
QQuickWindow::setPosition(screenPos);
}
-void RenderWidgetHostViewQtDelegateQuickWindow::setTooltip(const QString &tooltip)
-{
- Q_UNUSED(tooltip);
-}
-
} // namespace QtWebEngineCore
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h
index 699b4ce9e..d0a5e480c 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h
+++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h
@@ -69,13 +69,14 @@ public:
virtual QWindow* window() const Q_DECL_OVERRIDE;
virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE;
virtual QSGLayer *createLayer() Q_DECL_OVERRIDE;
- virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE;
+ virtual QSGInternalImageNode *createImageNode() Q_DECL_OVERRIDE;
+ virtual QSGTextureNode *createTextureNode() Q_DECL_OVERRIDE;
+ virtual QSGRectangleNode *createRectangleNode() Q_DECL_OVERRIDE;
virtual void update() Q_DECL_OVERRIDE;
virtual void updateCursor(const QCursor &) Q_DECL_OVERRIDE;
virtual void resize(int width, int height) Q_DECL_OVERRIDE;
virtual void move(const QPoint &screenPos) Q_DECL_OVERRIDE;
virtual void inputMethodStateChanged(bool) Q_DECL_OVERRIDE {}
- virtual void setTooltip(const QString &tooltip) Q_DECL_OVERRIDE;
virtual void setClearColor(const QColor &) Q_DECL_OVERRIDE { }
private:
diff --git a/src/webengine/ui/PromptDialog.qml b/src/webengine/ui/PromptDialog.qml
index 657bf7631..d9fc61cf8 100644
--- a/src/webengine/ui/PromptDialog.qml
+++ b/src/webengine/ui/PromptDialog.qml
@@ -53,6 +53,10 @@ ApplicationWindow {
height: 100
flags: Qt.Dialog
+ onClosing: {
+ rejected();
+ }
+
function open() {
show();
}
diff --git a/src/webengine/ui/ToolTip.qml b/src/webengine/ui/ToolTip.qml
new file mode 100644
index 000000000..96033e8f1
--- /dev/null
+++ b/src/webengine/ui/ToolTip.qml
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+
+Item {
+ id: toolTipContainer
+ z: 9999
+ width: content.width
+ height: content.height
+ visible: false
+
+ property alias text: toolTip.text
+ property int delayTimerInterval: 1000
+ property int hideTimerInterval: 1500
+
+ Timer {
+ id: delayTimer
+ interval: delayTimerInterval
+ onTriggered: {
+ toolTipContainer.visible = true
+ hideTimer.start()
+ }
+ }
+
+ Timer {
+ id: hideTimer
+ interval: hideTimerInterval
+ onTriggered: toolTipContainer.visible = false
+ }
+
+ Rectangle {
+ id: content
+ color: "#f8eabf"
+ border.color: "black"
+ anchors.centerIn: parent
+ width: toolTip.contentWidth + 10
+ height: toolTip.contentHeight + 10
+ radius: 3
+
+ Text {
+ id: toolTip
+ anchors {fill: parent; margins: 5}
+ wrapMode: Text.WrapAnywhere
+ }
+ }
+
+ function open() {
+ delayTimer.start();
+ }
+
+ function hide() {
+ hideTimer.start();
+ }
+}
diff --git a/src/webengine/ui/ui.pro b/src/webengine/ui/ui.pro
index 249d7dcfd..60dab61d6 100644
--- a/src/webengine/ui/ui.pro
+++ b/src/webengine/ui/ui.pro
@@ -14,6 +14,7 @@ QML_FILES += \
MenuItem.qml \
MenuSeparator.qml \
# Message Bubble
- MessageBubble.qml
+ MessageBubble.qml \
+ ToolTip.qml
load(qml_module)
diff --git a/src/webengine/ui2/AlertDialog.qml b/src/webengine/ui2/AlertDialog.qml
new file mode 100644
index 000000000..4f63c5b70
--- /dev/null
+++ b/src/webengine/ui2/AlertDialog.qml
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 2.0 as Controls
+import QtQuick.Dialogs 1.2
+import QtQuick.Layouts 1.0
+
+Dialog {
+ property alias text: message.text
+ property bool handled: false
+ signal accepted()
+ signal rejected()
+ title: qsTr("Alert Dialog")
+ modality: Qt.NonModal
+
+ //handle the case where users simply closes the dialog
+ onVisibilityChanged: {
+ if (visible == false && handled == false) {
+ handled = true;
+ rejected();
+ } else {
+ handled = false;
+ }
+ }
+
+ function acceptDialog() {
+ accepted();
+ handled = true;
+ close();
+ }
+
+ contentItem: ColumnLayout {
+ id: rootLayout
+ anchors.fill: parent
+ anchors.margins: 4
+ property int minimumWidth: rootLayout.implicitWidth + rootLayout.doubleMargins
+ property int minimumHeight: rootLayout.implicitHeight + rootLayout.doubleMargins
+ property int doubleMargins: anchors.margins * 2
+ SystemPalette { id: palette; colorGroup: SystemPalette.Active }
+ RowLayout {
+ Layout.alignment: Qt.AlignRight
+ spacing: 8
+ Image {
+ source: "information.png"
+ }
+ Text {
+ id: message
+ Layout.fillWidth: true
+ color: palette.windowText
+ }
+ }
+ Item {
+ Layout.fillHeight: true
+ }
+ Controls.Button {
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("OK")
+ onClicked: acceptDialog()
+ }
+ }
+}
diff --git a/src/webengine/ui2/AuthenticationDialog.qml b/src/webengine/ui2/AuthenticationDialog.qml
new file mode 100644
index 000000000..52fcce3f1
--- /dev/null
+++ b/src/webengine/ui2/AuthenticationDialog.qml
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 2.0 as Controls
+import QtQuick.Dialogs 1.2
+import QtQuick.Layouts 1.0
+
+Dialog {
+ property alias text: message.text
+ property bool handled: false
+ signal accepted(string user, string password)
+ signal rejected()
+ title: qsTr("Authentication Required")
+ modality: Qt.NonModal
+
+ //handle the case where users simply closes the dialog
+ onVisibilityChanged: {
+ if (visible == false && handled == false) {
+ handled = true;
+ rejected();
+ } else {
+ handled = false;
+ }
+ }
+
+ function acceptDialog() {
+ accepted(userField.text, passwordField.text);
+ handled = true;
+ close();
+ }
+
+ function rejectDialog() {
+ rejected();
+ handled = true;
+ close();
+ }
+
+ contentItem: ColumnLayout {
+ id: rootLayout
+ anchors.fill: parent
+ anchors.margins: 4
+ property int minimumWidth: rootLayout.implicitWidth + rootLayout.doubleMargins
+ property int minimumHeight: rootLayout.implicitHeight + rootLayout.doubleMargins
+
+ property int doubleMargins: anchors.margins * 2
+
+ SystemPalette { id: palette; colorGroup: SystemPalette.Active }
+ Text {
+ id: message
+ color: palette.windowText
+ }
+ GridLayout {
+ columns: 2
+ Controls.Label {
+ text: qsTr("Username:")
+ color: palette.windowText
+ }
+ Controls.TextField {
+ id: userField
+ focus: true
+ Layout.fillWidth: true
+ onAccepted: {
+ if (userField.text && passwordField.text)
+ acceptDialog();
+ }
+ }
+ Controls.Label {
+ text: qsTr("Password:")
+ color: palette.windowText
+ }
+ Controls.TextField {
+ id: passwordField
+ Layout.fillWidth: true
+ echoMode: TextInput.Password
+ onAccepted: {
+ if (userField.text && passwordField.text)
+ acceptDialog();
+ }
+ }
+ }
+ Item {
+ Layout.fillHeight: true
+ }
+ RowLayout {
+ Layout.alignment: Qt.AlignRight
+ spacing: 8
+ Controls.Button {
+ id: cancelButton
+ text: qsTr("Cancel")
+ onClicked: rejectDialog()
+ }
+ Controls.Button {
+ text: qsTr("Log In")
+ onClicked: acceptDialog()
+ }
+ }
+ }
+}
diff --git a/src/webengine/ui2/ConfirmDialog.qml b/src/webengine/ui2/ConfirmDialog.qml
new file mode 100644
index 000000000..0649d3654
--- /dev/null
+++ b/src/webengine/ui2/ConfirmDialog.qml
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 2.0 as Controls
+import QtQuick.Dialogs 1.2
+import QtQuick.Layouts 1.0
+
+Dialog {
+ property alias text: message.text
+ property bool handled: false
+ signal accepted()
+ signal rejected()
+ title: qsTr("Alert Dialog")
+ modality: Qt.NonModal
+
+ //handle the case where users simply closes the dialog
+ onVisibilityChanged: {
+ if (visible == false && handled == false) {
+ handled = true;
+ rejected();
+ } else {
+ handled = false;
+ }
+ }
+
+ function acceptDialog() {
+ accepted();
+ handled = true;
+ close();
+ }
+
+ function rejectDialog() {
+ rejected();
+ handled = true;
+ close();
+ }
+
+ contentItem: ColumnLayout {
+ id: rootLayout
+ anchors.fill: parent
+ anchors.margins: 4
+ property int minimumWidth: rootLayout.implicitWidth + rootLayout.doubleMargins
+ property int minimumHeight: rootLayout.implicitHeight + rootLayout.doubleMargins
+ property int doubleMargins: anchors.margins * 2
+ SystemPalette { id: palette; colorGroup: SystemPalette.Active }
+ RowLayout {
+ Layout.alignment: Qt.AlignRight
+ spacing: 8
+ Image {
+ source: "question.png"
+ }
+ Text {
+ id: message
+ Layout.fillWidth: true
+ color: palette.windowText
+ }
+ }
+ Item {
+ Layout.fillHeight: true
+ }
+ RowLayout {
+ Layout.alignment: Qt.AlignRight
+ spacing: 8
+ Controls.Button {
+ text: qsTr("OK")
+ onClicked: acceptDialog()
+ }
+ Controls.Button {
+ text: qsTr("Cancel")
+ onClicked: rejectDialog()
+ }
+ }
+ }
+}
diff --git a/src/webengine/ui2/Menu.qml b/src/webengine/ui2/Menu.qml
new file mode 100644
index 000000000..0e7b869f5
--- /dev/null
+++ b/src/webengine/ui2/Menu.qml
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 2.0 as Controls
+
+Controls.Menu {
+ id: menu
+ signal done()
+
+ // Use private API for now
+ onAboutToHide: doneTimer.start()
+
+ // WORKAROUND On Mac the Menu may be destroyed before the MenuItem
+ // is actually triggered (see qtbase commit 08cc9b9991ae9ab51)
+ Timer {
+ id: doneTimer
+ interval: 100
+ onTriggered: menu.done()
+ }
+}
diff --git a/src/webengine/ui2/MenuItem.qml b/src/webengine/ui2/MenuItem.qml
new file mode 100644
index 000000000..9bf8aac5e
--- /dev/null
+++ b/src/webengine/ui2/MenuItem.qml
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 2.0 as Controls
+
+Controls.MenuItem { }
+
diff --git a/tests/quicktestbrowser/ContextMenuExtras.qml b/src/webengine/ui2/MenuSeparator.qml
index c90c65495..0c664084a 100644
--- a/tests/quicktestbrowser/ContextMenuExtras.qml
+++ b/src/webengine/ui2/MenuSeparator.qml
@@ -5,7 +5,7 @@
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** $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
@@ -14,36 +14,29 @@
** 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 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+** 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.1
-import QtWebEngine.UIDelegates 1.0
-
-VisualItemModel {
- MenuItem {
- text: "An application specific entry"
- onTriggered: console.log("Application specific action triggered")
- }
- Menu {
- title: "Extras Submenu"
- MenuItem {
- text: "something"
- onTriggered: console.log("something triggered")
- }
- MenuItem {
- text: "something else"
- enabled: false
- }
- }
-}
+import QtQuick 2.5
+Item { id: dummy }
diff --git a/src/webengine/ui2/PromptDialog.qml b/src/webengine/ui2/PromptDialog.qml
new file mode 100644
index 000000000..880213e36
--- /dev/null
+++ b/src/webengine/ui2/PromptDialog.qml
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 2.0 as Controls
+import QtQuick.Layouts 1.0
+import QtQuick.Dialogs 1.2
+
+Dialog {
+ property alias text: message.text
+ property alias prompt: field.text
+ property bool handled: false
+ signal input(string text)
+ signal accepted()
+ signal rejected()
+ title: qsTr("Prompt Dialog")
+ modality: Qt.NonModal
+
+ //handle the case where users simply closes the dialog
+ onVisibilityChanged: {
+ if (visible == false && handled == false) {
+ handled = true;
+ rejected();
+ } else {
+ handled = false;
+ }
+ }
+
+ function acceptDialog() {
+ input(field.text);
+ accepted();
+ handled = true;
+ close();
+ }
+
+ function rejectDialog() {
+ rejected();
+ handled = true;
+ close();
+ }
+
+ contentItem: ColumnLayout {
+ id: rootLayout
+ anchors.fill: parent
+ anchors.margins: 4
+ property int minimumWidth: rootLayout.implicitWidth + rootLayout.doubleMargins
+ property int minimumHeight: rootLayout.implicitHeight + rootLayout.doubleMargins
+ property int doubleMargins: anchors.margins * 2
+ SystemPalette { id: palette; colorGroup: SystemPalette.Active }
+ Text {
+ id: message
+ Layout.fillWidth: true
+ color: palette.windowText
+ }
+ Controls.TextField {
+ id:field
+ focus: true
+ Layout.fillWidth: true
+ onAccepted: acceptDialog()
+ }
+ Item {
+ Layout.fillHeight: true
+ }
+ RowLayout {
+ Layout.alignment: Qt.AlignRight
+ spacing: 8
+ Controls.Button {
+ text: qsTr("OK")
+ onClicked: acceptDialog()
+ }
+ Controls.Button {
+ text: qsTr("Cancel")
+ onClicked: rejectDialog()
+ }
+ }
+ }
+
+}
diff --git a/src/webengine/ui2/ToolTip.qml b/src/webengine/ui2/ToolTip.qml
new file mode 100644
index 000000000..91645a0f4
--- /dev/null
+++ b/src/webengine/ui2/ToolTip.qml
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+import QtQuick.Controls 2.0
+
+ToolTip {
+ delay: 1000
+ timeout: 1500
+}
diff --git a/src/webengine/ui2/information.png b/src/webengine/ui2/information.png
new file mode 100644
index 000000000..0a2eb87d1
--- /dev/null
+++ b/src/webengine/ui2/information.png
Binary files differ
diff --git a/src/webengine/ui2/qmldir b/src/webengine/ui2/qmldir
new file mode 100644
index 000000000..8ab0d3671
--- /dev/null
+++ b/src/webengine/ui2/qmldir
@@ -0,0 +1,2 @@
+# Internal module
+module QtWebEngine/Controls2Delegates
diff --git a/src/webengine/ui2/question.png b/src/webengine/ui2/question.png
new file mode 100644
index 000000000..2dd92fd79
--- /dev/null
+++ b/src/webengine/ui2/question.png
Binary files differ
diff --git a/src/webengine/ui2/ui2.pro b/src/webengine/ui2/ui2.pro
new file mode 100644
index 000000000..4628d40b5
--- /dev/null
+++ b/src/webengine/ui2/ui2.pro
@@ -0,0 +1,18 @@
+TARGETPATH = QtWebEngine/Controls2Delegates
+
+QML_FILES += \
+ # Authentication Dialog
+ AuthenticationDialog.qml \
+ # JS Dialogs
+ AlertDialog.qml \
+ ConfirmDialog.qml \
+ PromptDialog.qml \
+ # Menus. Based on Qt Quick Controls
+ Menu.qml \
+ MenuItem.qml \
+ MenuSeparator.qml \
+ ToolTip.qml \
+ information.png \
+ question.png
+
+load(qml_module)
diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp
index 6ff12b53f..4ca4ba98c 100644
--- a/src/webengine/ui_delegates_manager.cpp
+++ b/src/webengine/ui_delegates_manager.cpp
@@ -50,6 +50,10 @@
#include <QQmlContext>
#include <QQmlEngine>
#include <QQmlProperty>
+#include <QCursor>
+#include <QList>
+#include <QScreen>
+#include <QGuiApplication>
// Uncomment for QML debugging
//#define UI_DELEGATES_DEBUG
@@ -77,20 +81,29 @@ static QString fileNameForComponent(UIDelegatesManager::ComponentType type)
return QString();
}
-static QString getUIDelegatesImportDir(QQmlEngine *engine) {
- static QString importDir;
- static bool initialized = false;
- if (initialized)
- return importDir;
- Q_FOREACH (const QString &path, engine->importPathList()) {
- QFileInfo fi(path % QLatin1String("/QtWebEngine/UIDelegates/"));
- if (fi.exists()) {
- importDir = fi.absolutePath();
- break;
- }
- }
- initialized = true;
- return importDir;
+static QPoint calculateToolTipPosition(QPoint &position, QSize &toolTip) {
+ QRect screen;
+ QList<QScreen *> screens = QGuiApplication::screens();
+ Q_FOREACH (const QScreen *src, screens)
+ if (src->availableGeometry().contains(position))
+ screen = src->availableGeometry();
+
+ position += QPoint(2, 16);
+
+ if (position.x() + toolTip.width() > screen.x() + screen.width())
+ position.rx() -= 4 + toolTip.width();
+ if (position.y() + toolTip.height() > screen.y() + screen.height())
+ position.ry() -= 24 + toolTip.height();
+ if (position.y() < screen.y())
+ position.setY(screen.y());
+ if (position.x() + toolTip.width() > screen.x() + screen.width())
+ position.setX(screen.x() + screen.width() - toolTip.width());
+ if (position.x() < screen.x())
+ position.setX(screen.x());
+ if (position.y() + toolTip.height() > screen.y() + screen.height())
+ position.setY(screen.y() + screen.height() - toolTip.height());
+
+ return position;
}
const char *defaultPropertyName(QObject *obj)
@@ -116,20 +129,37 @@ MenuItemHandler::MenuItemHandler(QObject *parent)
UIDelegatesManager::UIDelegatesManager(QQuickWebEngineView *view)
: m_view(view)
, m_messageBubbleItem(0)
+ , m_toolTip(nullptr)
FOR_EACH_COMPONENT_TYPE(COMPONENT_MEMBER_INIT, NO_SEPARATOR)
{
}
+UIDelegatesManager::~UIDelegatesManager()
+{
+}
+
#define COMPONENT_MEMBER_CASE_STATEMENT(TYPE, COMPONENT) \
case TYPE: \
component = &COMPONENT##Component; \
break;
+bool UIDelegatesManager::initializeImportDirs(QStringList &dirs, QQmlEngine *engine) {
+ foreach (const QString &path, engine->importPathList()) {
+ QFileInfo fi(path % QLatin1String("/QtWebEngine/UIDelegates/"));
+ if (fi.exists()) {
+ dirs << fi.absolutePath();
+ return true;
+ }
+ }
+ return false;
+}
+
bool UIDelegatesManager::ensureComponentLoaded(ComponentType type)
{
QQmlEngine* engine = qmlEngine(m_view);
- if (getUIDelegatesImportDir(engine).isNull())
+ if (m_importDirs.isEmpty() && !initializeImportDirs(m_importDirs, engine))
return false;
+
QQmlComponent **component;
switch (type) {
FOR_EACH_COMPONENT_TYPE(COMPONENT_MEMBER_CASE_STATEMENT, NO_SEPARATOR)
@@ -146,20 +176,25 @@ bool UIDelegatesManager::ensureComponentLoaded(ComponentType type)
#endif
if (!engine)
return false;
- QFileInfo fi(getUIDelegatesImportDir(engine) % QLatin1Char('/') % fileName);
- if (!fi.exists())
- return false;
- // FIXME: handle async loading
- *component = (new QQmlComponent(engine, QUrl::fromLocalFile(fi.absoluteFilePath()), QQmlComponent::PreferSynchronous, m_view));
-
- if ((*component)->status() != QQmlComponent::Ready) {
- Q_FOREACH (const QQmlError& err, (*component)->errors())
- qWarning("QtWebEngine: component error: %s\n", qPrintable(err.toString()));
- delete *component;
- *component = 0;
- return false;
+
+ foreach (const QString &importDir, m_importDirs) {
+ QFileInfo fi(importDir % QLatin1Char('/') % fileName);
+ if (!fi.exists())
+ continue;
+ // FIXME: handle async loading
+ *component = (new QQmlComponent(engine, QUrl::fromLocalFile(fi.absoluteFilePath()),
+ QQmlComponent::PreferSynchronous, m_view));
+
+ if ((*component)->status() != QQmlComponent::Ready) {
+ foreach (const QQmlError &err, (*component)->errors())
+ qWarning("QtWebEngine: component error: %s\n", qPrintable(err.toString()));
+ delete *component;
+ *component = nullptr;
+ return false;
+ }
+ return true;
}
- return true;
+ return false;
}
#define CHECK_QML_SIGNAL_PROPERTY(prop, location) \
@@ -211,11 +246,11 @@ QObject *UIDelegatesManager::addMenu(QObject *parentMenu, const QString &title,
{
Q_ASSERT(parentMenu);
if (!ensureComponentLoaded(Menu))
- return 0;
+ return nullptr;
QQmlContext *context = qmlContext(m_view);
QObject *menu = menuComponent->beginCreate(context);
// set visual parent for non-Window-based menus
- if (QQuickItem* item = qobject_cast<QQuickItem*>(menu))
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(menu))
item->setParentItem(m_view);
if (!title.isEmpty())
@@ -291,7 +326,7 @@ void UIDelegatesManager::showDialog(QSharedPointer<JavaScriptDialogController> d
QQmlContext *context = qmlContext(m_view);
QObject *dialog = dialogComponent->beginCreate(context);
// set visual parent for non-Window-based dialogs
- if (QQuickItem* item = qobject_cast<QQuickItem*>(dialog))
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(dialog))
item->setParentItem(m_view);
dialog->setParent(m_view);
QQmlProperty textProp(dialog, QStringLiteral("text"));
@@ -317,8 +352,6 @@ void UIDelegatesManager::showDialog(QSharedPointer<JavaScriptDialogController> d
CHECK_QML_SIGNAL_PROPERTY(inputSignal, dialogComponent->url());
static int setTextIndex = dialogController->metaObject()->indexOfSlot("textProvided(QString)");
QObject::connect(dialog, inputSignal.method(), dialogController.data(), dialogController->metaObject()->method(setTextIndex));
- QQmlProperty closingSignal(dialog, QStringLiteral("onClosing"));
- QObject::connect(dialog, closingSignal.method(), dialogController.data(), dialogController->metaObject()->method(rejectIndex));
}
dialogComponent->completeCreate();
@@ -339,7 +372,7 @@ void UIDelegatesManager::showColorDialog(QSharedPointer<ColorChooserController>
QQmlContext *context = qmlContext(m_view);
QObject *colorDialog = colorDialogComponent->beginCreate(context);
- if (QQuickItem* item = qobject_cast<QQuickItem*>(colorDialog))
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(colorDialog))
item->setParentItem(m_view);
colorDialog->setParent(m_view);
@@ -379,7 +412,7 @@ void UIDelegatesManager::showDialog(QSharedPointer<AuthenticationDialogControlle
QQmlContext *context = qmlContext(m_view);
QObject *authenticationDialog = authenticationDialogComponent->beginCreate(context);
// set visual parent for non-Window-based dialogs
- if (QQuickItem* item = qobject_cast<QQuickItem*>(authenticationDialog))
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(authenticationDialog))
item->setParentItem(m_view);
authenticationDialog->setParent(m_view);
@@ -412,7 +445,7 @@ void UIDelegatesManager::showDialog(QSharedPointer<AuthenticationDialogControlle
QMetaObject::invokeMethod(authenticationDialog, "open");
}
-void UIDelegatesManager::showFilePicker(FilePickerController *controller)
+void UIDelegatesManager::showFilePicker(QSharedPointer<FilePickerController> controller)
{
if (!ensureComponentLoaded(FilePicker))
@@ -420,7 +453,7 @@ void UIDelegatesManager::showFilePicker(FilePickerController *controller)
QQmlContext *context = qmlContext(m_view);
QObject *filePicker = filePickerComponent->beginCreate(context);
- if (QQuickItem* item = qobject_cast<QQuickItem*>(filePicker))
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(filePicker))
item->setParentItem(m_view);
filePicker->setParent(m_view);
filePickerComponent->completeCreate();
@@ -442,16 +475,14 @@ void UIDelegatesManager::showFilePicker(FilePickerController *controller)
Q_UNREACHABLE();
}
- controller->setParent(filePicker);
-
QQmlProperty filesPickedSignal(filePicker, QStringLiteral("onFilesSelected"));
CHECK_QML_SIGNAL_PROPERTY(filesPickedSignal, filePickerComponent->url());
QQmlProperty rejectSignal(filePicker, QStringLiteral("onRejected"));
CHECK_QML_SIGNAL_PROPERTY(rejectSignal, filePickerComponent->url());
static int acceptedIndex = controller->metaObject()->indexOfSlot("accepted(QVariant)");
- QObject::connect(filePicker, filesPickedSignal.method(), controller, controller->metaObject()->method(acceptedIndex));
+ QObject::connect(filePicker, filesPickedSignal.method(), controller.data(), controller->metaObject()->method(acceptedIndex));
static int rejectedIndex = controller->metaObject()->indexOfSlot("rejected()");
- QObject::connect(filePicker, rejectSignal.method(), controller, controller->metaObject()->method(rejectedIndex));
+ QObject::connect(filePicker, rejectSignal.method(), controller.data(), controller->metaObject()->method(rejectedIndex));
// delete when done.
static int deleteLaterIndex = filePicker->metaObject()->indexOfSlot("deleteLater()");
@@ -461,6 +492,11 @@ void UIDelegatesManager::showFilePicker(FilePickerController *controller)
QMetaObject::invokeMethod(filePicker, "open");
}
+void UIDelegatesManager::showMenu(QObject *menu)
+{
+ QMetaObject::invokeMethod(menu, "popup");
+}
+
void UIDelegatesManager::showMessageBubble(const QRect &anchor, const QString &mainText, const QString &subText)
{
if (!ensureComponentLoaded(MessageBubble))
@@ -493,4 +529,118 @@ void UIDelegatesManager::moveMessageBubble(const QRect &anchor)
QQmlProperty(m_messageBubbleItem.data(), QStringLiteral("y")).write(anchor.y() + anchor.size().height());
}
+void UIDelegatesManager::showToolTip(const QString &text)
+{
+ if (!ensureComponentLoaded(ToolTip))
+ return;
+
+ if (text.isEmpty()) {
+ m_toolTip.reset();
+ return;
+ }
+
+ if (!m_toolTip.isNull())
+ return;
+
+ QQmlContext *context = qmlContext(m_view);
+ m_toolTip.reset(toolTipComponent->beginCreate(context));
+ if (QQuickItem *item = qobject_cast<QQuickItem *>(m_toolTip.data()))
+ item->setParentItem(m_view);
+ m_toolTip->setParent(m_view);
+ toolTipComponent->completeCreate();
+
+ QQmlProperty(m_toolTip.data(), QStringLiteral("text")).write(text);
+
+ int height = QQmlProperty(m_toolTip.data(), QStringLiteral("height")).read().toInt();
+ int width = QQmlProperty(m_toolTip.data(), QStringLiteral("width")).read().toInt();
+ QSize toolTipSize(width, height);
+ QPoint position = m_view->cursor().pos();
+ position = m_view->mapFromGlobal(calculateToolTipPosition(position, toolTipSize)).toPoint();
+
+ QQmlProperty(m_toolTip.data(), QStringLiteral("x")).write(position.x());
+ QQmlProperty(m_toolTip.data(), QStringLiteral("y")).write(position.y());
+
+ QMetaObject::invokeMethod(m_toolTip.data(), "open");
+}
+
+UI2DelegatesManager::UI2DelegatesManager(QQuickWebEngineView *view) : UIDelegatesManager(view)
+{
+
+}
+
+bool UI2DelegatesManager::initializeImportDirs(QStringList &dirs, QQmlEngine *engine)
+{
+ foreach (const QString &path, engine->importPathList()) {
+ QFileInfo fi1(path % QLatin1String("/QtWebEngine/Controls2Delegates/"));
+ QFileInfo fi2(path % QLatin1String("/QtWebEngine/UIDelegates/"));
+ if (fi1.exists() && fi2.exists()) {
+ dirs << fi1.absolutePath() << fi2.absolutePath();
+ return true;
+ }
+ }
+ return false;
+}
+
+QObject *UI2DelegatesManager::addMenu(QObject *parentMenu, const QString &title, const QPoint &pos)
+{
+ Q_ASSERT(parentMenu);
+ if (!ensureComponentLoaded(Menu))
+ return nullptr;
+ QQmlContext *context = qmlContext(m_view);
+ QObject *menu = menuComponent->beginCreate(context);
+
+ // set visual parent for non-Window-based menus
+ if (QQuickItem *item = qobject_cast<QQuickItem*>(menu))
+ item->setParentItem(m_view);
+
+ if (!title.isEmpty())
+ menu->setProperty("title", title);
+ if (!pos.isNull()) {
+ menu->setProperty("x", pos.x());
+ menu->setProperty("y", pos.y());
+ }
+
+ menu->setParent(parentMenu);
+ QQmlProperty doneSignal(menu, QStringLiteral("onDone"));
+ CHECK_QML_SIGNAL_PROPERTY(doneSignal, menuComponent->url())
+ static int deleteLaterIndex = menu->metaObject()->indexOfSlot("deleteLater()");
+ QObject::connect(menu, doneSignal.method(), menu, menu->metaObject()->method(deleteLaterIndex));
+ menuComponent->completeCreate();
+ return menu;
+}
+
+void UI2DelegatesManager::addMenuItem(MenuItemHandler *menuItemHandler, const QString &text,
+ const QString &/*iconName*/, bool enabled,
+ bool checkable, bool checked)
+{
+ Q_ASSERT(menuItemHandler);
+ if (!ensureComponentLoaded(MenuItem))
+ return;
+
+ QObject *it = menuItemComponent->beginCreate(qmlContext(m_view));
+
+ it->setProperty("text", text);
+ it->setProperty("enabled", enabled);
+ it->setProperty("checked", checked);
+ it->setProperty("checkable", checkable);
+
+ QQmlProperty signal(it, QStringLiteral("onTriggered"));
+ CHECK_QML_SIGNAL_PROPERTY(signal, menuItemComponent->url());
+ QObject::connect(it, signal.method(), menuItemHandler,
+ QMetaMethod::fromSignal(&MenuItemHandler::triggered));
+ menuItemComponent->completeCreate();
+
+ QObject *menu = menuItemHandler->parent();
+ it->setParent(menu);
+
+ QQmlListReference entries(menu, defaultPropertyName(menu), qmlEngine(m_view));
+ if (entries.isValid())
+ entries.append(it);
+}
+
+void UI2DelegatesManager::showMenu(QObject *menu)
+{
+ QMetaObject::invokeMethod(menu, "open");
+}
+
} // namespace QtWebEngineCore
diff --git a/src/webengine/ui_delegates_manager.h b/src/webengine/ui_delegates_manager.h
index b63aa91f1..54ecf0986 100644
--- a/src/webengine/ui_delegates_manager.h
+++ b/src/webengine/ui_delegates_manager.h
@@ -59,7 +59,8 @@
F(PromptDialog, promptDialog) SEPARATOR \
F(FilePicker, filePicker) SEPARATOR \
F(MessageBubble, messageBubble) SEPARATOR \
- F(AuthenticationDialog, authenticationDialog) SEPARATOR
+ F(AuthenticationDialog, authenticationDialog) SEPARATOR \
+ F(ToolTip, toolTip) SEPARATOR \
#define COMMA_SEPARATOR ,
#define SEMICOLON_SEPARATOR ;
@@ -73,6 +74,7 @@ class QQmlContext;
class QQmlComponent;
class QQuickItem;
class QQuickWebEngineView;
+class QQmlEngine;
QT_END_NAMESPACE
namespace QtWebEngineCore {
@@ -102,25 +104,35 @@ public:
};
UIDelegatesManager(QQuickWebEngineView *);
+ virtual ~UIDelegatesManager();
- void addMenuItem(MenuItemHandler *menuItemHandler, const QString &text, const QString &iconName = QString(),
- bool enabled = true, bool checkable = false, bool checked = true);
+ virtual bool initializeImportDirs(QStringList &dirs, QQmlEngine *engine);
+ virtual void addMenuItem(MenuItemHandler *menuItemHandler, const QString &text,
+ const QString &iconName = QString(),
+ bool enabled = true,
+ bool checkable = false, bool checked = true);
void addMenuSeparator(QObject *menu);
- QObject *addMenu(QObject *parentMenu, const QString &title, const QPoint &pos = QPoint());
+ virtual QObject *addMenu(QObject *parentMenu, const QString &title,
+ const QPoint &pos = QPoint());
QQmlContext *creationContextForComponent(QQmlComponent *);
void showColorDialog(QSharedPointer<ColorChooserController>);
void showDialog(QSharedPointer<JavaScriptDialogController>);
void showDialog(QSharedPointer<AuthenticationDialogController>);
- void showFilePicker(FilePickerController *controller);
- void showMessageBubble(const QRect &anchor, const QString &mainText, const QString &subText);
+ void showFilePicker(QSharedPointer<FilePickerController>);
+ virtual void showMenu(QObject *menu);
+ void showMessageBubble(const QRect &anchor, const QString &mainText,
+ const QString &subText);
void hideMessageBubble();
void moveMessageBubble(const QRect &anchor);
+ void showToolTip(const QString &text);
-private:
+protected:
bool ensureComponentLoaded(ComponentType);
QQuickWebEngineView *m_view;
QScopedPointer<QQuickItem> m_messageBubbleItem;
+ QScopedPointer<QObject> m_toolTip;
+ QStringList m_importDirs;
FOR_EACH_COMPONENT_TYPE(MEMBER_DECLARATION, SEMICOLON_SEPARATOR)
@@ -128,6 +140,24 @@ private:
};
+// delegate manager for qtquickcontrols2 with fallback to qtquickcontrols1
+
+class UI2DelegatesManager : public UIDelegatesManager
+{
+public:
+ UI2DelegatesManager(QQuickWebEngineView *);
+ bool initializeImportDirs(QStringList &dirs, QQmlEngine *engine) override;
+ QObject *addMenu(QObject *parentMenu, const QString &title,
+ const QPoint &pos = QPoint()) override;
+ void addMenuItem(MenuItemHandler *menuItemHandler, const QString &text,
+ const QString &iconName = QString(),
+ bool enabled = true,
+ bool checkable = false, bool checked = false) override;
+ void showMenu(QObject *menu) override;
+ Q_DISABLE_COPY(UI2DelegatesManager)
+
+};
+
} // namespace QtWebEngineCore
#endif // UI_DELEGATES_MANAGER_H
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index 236881958..e84188682 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -12,7 +12,8 @@ INCLUDEPATH += $$PWD api ../core ../core/api
SOURCES = \
api/qquickwebenginecertificateerror.cpp \
- api/qquickwebenginecontextmenudata.cpp \
+ api/qquickwebenginecontextmenurequest.cpp \
+ api/qquickwebenginedialogrequests.cpp \
api/qquickwebenginedownloaditem.cpp \
api/qquickwebenginehistory.cpp \
api/qquickwebenginefaviconprovider.cpp \
@@ -33,7 +34,8 @@ HEADERS = \
api/qtwebengineglobal.h \
api/qtwebengineglobal_p.h \
api/qquickwebenginecertificateerror_p.h \
- api/qquickwebenginecontextmenudata_p.h \
+ api/qquickwebenginecontextmenurequest_p.h \
+ api/qquickwebenginedialogrequests_p.h \
api/qquickwebenginedownloaditem_p.h \
api/qquickwebenginedownloaditem_p_p.h \
api/qquickwebenginehistory_p.h \
diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.cpp b/src/webenginewidgets/api/qwebenginecertificateerror.cpp
index 289bb7ec0..a0641c9dd 100644
--- a/src/webenginewidgets/api/qwebenginecertificateerror.cpp
+++ b/src/webenginewidgets/api/qwebenginecertificateerror.cpp
@@ -104,6 +104,8 @@ QWebEngineCertificateError::~QWebEngineCertificateError()
\value CertificateWeakKey The certificate contains a weak key.
\value CertificateNameConstraintViolation The certificate claimed DNS names that are in violation of name constraints.
\value CertificateValidityTooLong The certificate has a validity period that is too long. (Added in Qt 5.7)
+ \value CertificateTransparencyRequired Certificate Transparency was required for this connection, but the server
+ did not provide CT information that complied with the policy. (Added in Qt 5.8)
*/
/*!
diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.h b/src/webenginewidgets/api/qwebenginecertificateerror.h
index 7cb6341bc..82ac281be 100644
--- a/src/webenginewidgets/api/qwebenginecertificateerror.h
+++ b/src/webenginewidgets/api/qwebenginecertificateerror.h
@@ -70,6 +70,7 @@ public:
CertificateWeakKey = -211,
CertificateNameConstraintViolation = -212,
CertificateValidityTooLong = -213,
+ CertificateTransparencyRequired = -214,
};
Error error() const;
diff --git a/src/webenginewidgets/api/qwebenginecontextmenudata.cpp b/src/webenginewidgets/api/qwebenginecontextmenudata.cpp
index 4d72071e5..37b65403a 100644
--- a/src/webenginewidgets/api/qwebenginecontextmenudata.cpp
+++ b/src/webenginewidgets/api/qwebenginecontextmenudata.cpp
@@ -135,7 +135,7 @@ void QWebEngineContextMenuData::reset()
*/
QPoint QWebEngineContextMenuData::position() const
{
- return d ? d->pos : QPoint();
+ return d ? d->position() : QPoint();
}
/*!
@@ -143,7 +143,7 @@ QPoint QWebEngineContextMenuData::position() const
*/
QString QWebEngineContextMenuData::linkText() const
{
- return d ? d->linkText : QString();
+ return d ? d->linkText() : QString();
}
/*!
@@ -151,7 +151,7 @@ QString QWebEngineContextMenuData::linkText() const
*/
QUrl QWebEngineContextMenuData::linkUrl() const
{
- return d ? d->linkUrl : QUrl();
+ return d ? d->linkUrl() : QUrl();
}
/*!
@@ -159,7 +159,7 @@ QUrl QWebEngineContextMenuData::linkUrl() const
*/
QString QWebEngineContextMenuData::selectedText() const
{
- return d ? d->selectedText : QString();
+ return d ? d->selectedText() : QString();
}
/*!
@@ -167,7 +167,7 @@ QString QWebEngineContextMenuData::selectedText() const
*/
QUrl QWebEngineContextMenuData::mediaUrl() const
{
- return d ? d->mediaUrl : QUrl();
+ return d ? d->mediaUrl() : QUrl();
}
/*!
@@ -175,7 +175,7 @@ QUrl QWebEngineContextMenuData::mediaUrl() const
*/
QWebEngineContextMenuData::MediaType QWebEngineContextMenuData::mediaType() const
{
- return d ? static_cast<QWebEngineContextMenuData::MediaType>(d->mediaType) : MediaTypeNone;
+ return d ? static_cast<QWebEngineContextMenuData::MediaType>(d->mediaType()) : MediaTypeNone;
}
/*!
@@ -183,7 +183,31 @@ QWebEngineContextMenuData::MediaType QWebEngineContextMenuData::mediaType() cons
*/
bool QWebEngineContextMenuData::isContentEditable() const
{
- return d ? d->isEditable : false;
+ return d ? d->isEditable() : false;
+}
+
+/*!
+ If the context is a word considered misspelled by the spell-checker, returns the misspelled word.
+
+ \since 5.8
+*/
+QString QWebEngineContextMenuData::misspelledWord() const
+{
+ if (d)
+ return d->misspelledWord();
+ return QString();
+}
+
+/*!
+ If the context is a word considered misspelled by the spell-checker, returns a list of suggested replacements.
+
+ \since 5.8
+*/
+QStringList QWebEngineContextMenuData::spellCheckerSuggestions() const
+{
+ if (d)
+ return d->spellCheckerSuggestions();
+ return QStringList();
}
/*!
diff --git a/src/webenginewidgets/api/qwebenginecontextmenudata.h b/src/webenginewidgets/api/qwebenginecontextmenudata.h
index d04b747c8..1a2ff8de4 100644
--- a/src/webenginewidgets/api/qwebenginecontextmenudata.h
+++ b/src/webenginewidgets/api/qwebenginecontextmenudata.h
@@ -76,6 +76,8 @@ public:
QUrl mediaUrl() const;
MediaType mediaType() const;
bool isContentEditable() const;
+ QString misspelledWord() const;
+ QStringList spellCheckerSuggestions() const;
private:
void reset();
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
index bfb0dd0e8..6f7865a50 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp
+++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
@@ -80,6 +80,7 @@ QWebEngineDownloadItemPrivate::QWebEngineDownloadItemPrivate(QWebEngineProfilePr
, downloadId(-1)
, downloadState(QWebEngineDownloadItem::DownloadCancelled)
, savePageFormat(QWebEngineDownloadItem::MimeHtmlSaveFormat)
+ , type(QWebEngineDownloadItem::Attachment)
, downloadUrl(url)
, totalBytes(-1)
, receivedBytes(0)
@@ -218,6 +219,22 @@ quint32 QWebEngineDownloadItem::id() const
*/
/*!
+ \enum QWebEngineDownloadItem::DownloadType
+ \since 5.8
+
+ Describes the requested download's type.
+
+ \value Attachment The web server's response includes a \c Content-Disposition header with the \c attachment directive.
+ If \c Content-Disposition is present in the reply, the web server is indicating that
+ the client should prompt the user to save the content regardless of the content type.
+ See \l {RFC 2616 section 19.5.1} for details.
+ \value DownloadAttribute The user clicked the hyperlink.
+ See \l {HTML download Attribute} for details.
+ \value UserRequested The user initiated the download.
+ \value SavePage The user saved a web page.
+*/
+
+/*!
Returns the download item's current state.
\sa QWebEngineDownloadItem::DownloadState
@@ -342,6 +359,18 @@ void QWebEngineDownloadItem::setSavePageFormat(QWebEngineDownloadItem::SavePageF
d->savePageFormat = format;
}
+/*!
+ Returns the requested download's type.
+ \since 5.8
+
+ */
+
+QWebEngineDownloadItem::DownloadType QWebEngineDownloadItem::type() const
+{
+ Q_D(const QWebEngineDownloadItem);
+ return d->type;
+}
+
QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p, QObject *parent)
: QObject(parent)
, d_ptr(p)
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.h b/src/webenginewidgets/api/qwebenginedownloaditem.h
index 80b5c06c5..4b58748ad 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem.h
+++ b/src/webenginewidgets/api/qwebenginedownloaditem.h
@@ -72,6 +72,14 @@ public:
};
Q_ENUM(SavePageFormat)
+ enum DownloadType {
+ Attachment = 0,
+ DownloadAttribute,
+ UserRequested,
+ SavePage
+ };
+ Q_ENUM(DownloadType)
+
quint32 id() const;
DownloadState state() const;
qint64 totalBytes() const;
@@ -83,6 +91,7 @@ public:
bool isFinished() const;
SavePageFormat savePageFormat() const;
void setSavePageFormat(SavePageFormat format);
+ DownloadType type() const;
public Q_SLOTS:
void accept();
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h
index ddb3b443a..9ddb45444 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem_p.h
+++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h
@@ -72,6 +72,7 @@ public:
quint32 downloadId;
QWebEngineDownloadItem::DownloadState downloadState;
QWebEngineDownloadItem::SavePageFormat savePageFormat;
+ QWebEngineDownloadItem::DownloadType type;
QString downloadPath;
const QUrl downloadUrl;
QString mimeType;
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 10b4452fb..8911b114f 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -90,6 +90,8 @@ QT_BEGIN_NAMESPACE
using namespace QtWebEngineCore;
+static const int MaxTooltipLength = 1024;
+
static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition)
{
switch (disposition) {
@@ -376,6 +378,13 @@ void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &re
m_callbacks.invoke(requestId, result);
}
+#ifndef QT_NO_PRINTER
+void QWebEnginePagePrivate::didPrintPageOnPrinter(quint64 requestId, bool result)
+{
+ m_callbacks.invoke(requestId, result);
+}
+#endif
+
void QWebEnginePagePrivate::passOnFocus(bool reverse)
{
if (view)
@@ -475,6 +484,9 @@ void QWebEnginePagePrivate::updateAction(QWebEnginePage::WebAction action) const
case QWebEnginePage::ReloadAndBypassCache:
enabled = !isLoading;
break;
+ case QWebEnginePage::ViewSource:
+ enabled = adapter->canViewSource();
+ break;
default:
break;
}
@@ -490,6 +502,7 @@ void QWebEnginePagePrivate::updateNavigationActions()
updateAction(QWebEnginePage::Stop);
updateAction(QWebEnginePage::Reload);
updateAction(QWebEnginePage::ReloadAndBypassCache);
+ updateAction(QWebEnginePage::ViewSource);
}
#ifndef QT_NO_ACTION
@@ -774,6 +787,29 @@ void QWebEnginePage::setBackgroundColor(const QColor &color)
}
/*!
+ * Save the currently loaded web page to disk.
+ *
+ * The web page is saved to \a filePath in the specified \a{format}.
+ *
+ * This is a short cut for the following actions:
+ * \list
+ * \li Trigger the Save web action.
+ * \li Accept the next download item and set the specified file path and save format.
+ * \endlist
+ *
+ * This function issues an asynchronous download request for the web page and returns immediately.
+ *
+ * \sa QWebEngineDownloadItem::SavePageFormat
+ * \since 5.8
+ */
+void QWebEnginePage::save(const QString &filePath,
+ QWebEngineDownloadItem::SavePageFormat format) const
+{
+ Q_D(const QWebEnginePage);
+ d->adapter->save(filePath, format);
+}
+
+/*!
\property QWebEnginePage::audioMuted
\brief whether the current page audio is muted.
\since 5.7
@@ -958,6 +994,9 @@ QAction *QWebEnginePage::action(WebAction action) const
case SavePage:
text = tr("Save &Page");
break;
+ case ViewSource:
+ text = tr("&View Page Source");
+ break;
case NoWebAction:
case WebActionCount:
Q_UNREACHABLE();
@@ -1022,122 +1061,122 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
d->adapter->unselect();
break;
case OpenLinkInThisWindow:
- if (menuData.linkUrl.isValid())
- setUrl(menuData.linkUrl);
+ if (menuData.linkUrl().isValid())
+ setUrl(menuData.linkUrl());
break;
case OpenLinkInNewWindow:
- if (menuData.linkUrl.isValid()) {
+ if (menuData.linkUrl().isValid()) {
QWebEnginePage *newPage = createWindow(WebBrowserWindow);
if (newPage)
- newPage->setUrl(menuData.linkUrl);
+ newPage->setUrl(menuData.linkUrl());
}
break;
case OpenLinkInNewTab:
- if (menuData.linkUrl.isValid()) {
+ if (menuData.linkUrl().isValid()) {
QWebEnginePage *newPage = createWindow(WebBrowserTab);
if (newPage)
- newPage->setUrl(menuData.linkUrl);
+ newPage->setUrl(menuData.linkUrl());
}
break;
case OpenLinkInNewBackgroundTab:
- if (menuData.linkUrl.isValid()) {
+ if (menuData.linkUrl().isValid()) {
QWebEnginePage *newPage = createWindow(WebBrowserBackgroundTab);
if (newPage)
- newPage->setUrl(menuData.linkUrl);
+ newPage->setUrl(menuData.linkUrl());
}
break;
case CopyLinkToClipboard:
- if (menuData.linkUrl.isValid()) {
- QString urlString = menuData.linkUrl.toString(QUrl::FullyEncoded);
- QString title = menuData.linkText.toHtmlEscaped();
+ if (menuData.linkUrl().isValid()) {
+ QString urlString = menuData.linkUrl().toString(QUrl::FullyEncoded);
+ QString title = menuData.linkText().toHtmlEscaped();
QMimeData *data = new QMimeData();
data->setText(urlString);
QString html = QStringLiteral("<a href=\"") + urlString + QStringLiteral("\">") + title + QStringLiteral("</a>");
data->setHtml(html);
- data->setUrls(QList<QUrl>() << menuData.linkUrl);
+ data->setUrls(QList<QUrl>() << menuData.linkUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case DownloadLinkToDisk:
- if (menuData.linkUrl.isValid())
- d->adapter->download(menuData.linkUrl, menuData.suggestedFileName);
+ if (menuData.linkUrl().isValid())
+ d->adapter->download(menuData.linkUrl(), menuData.suggestedFileName());
break;
case CopyImageToClipboard:
- if (menuData.hasImageContent &&
- (menuData.mediaType == WebEngineContextMenuData::MediaTypeImage ||
- menuData.mediaType == WebEngineContextMenuData::MediaTypeCanvas))
+ if (menuData.hasImageContent() &&
+ (menuData.mediaType() == WebEngineContextMenuData::MediaTypeImage ||
+ menuData.mediaType() == WebEngineContextMenuData::MediaTypeCanvas))
{
- d->adapter->copyImageAt(menuData.pos);
+ d->adapter->copyImageAt(menuData.position());
}
break;
case CopyImageUrlToClipboard:
- if (menuData.mediaUrl.isValid() && menuData.mediaType == WebEngineContextMenuData::MediaTypeImage) {
- QString urlString = menuData.mediaUrl.toString(QUrl::FullyEncoded);
- QString title = menuData.linkText;
+ if (menuData.mediaUrl().isValid() && menuData.mediaType() == WebEngineContextMenuData::MediaTypeImage) {
+ QString urlString = menuData.mediaUrl().toString(QUrl::FullyEncoded);
+ QString title = menuData.linkText();
if (!title.isEmpty())
title = QStringLiteral(" alt=\"%1\"").arg(title.toHtmlEscaped());
QMimeData *data = new QMimeData();
data->setText(urlString);
QString html = QStringLiteral("<img src=\"") + urlString + QStringLiteral("\"") + title + QStringLiteral("></img>");
data->setHtml(html);
- data->setUrls(QList<QUrl>() << menuData.mediaUrl);
+ data->setUrls(QList<QUrl>() << menuData.mediaUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case DownloadImageToDisk:
case DownloadMediaToDisk:
- if (menuData.mediaUrl.isValid())
- d->adapter->download(menuData.mediaUrl, menuData.suggestedFileName);
+ if (menuData.mediaUrl().isValid())
+ d->adapter->download(menuData.mediaUrl(), menuData.suggestedFileName());
break;
case CopyMediaUrlToClipboard:
- if (menuData.mediaUrl.isValid() &&
- (menuData.mediaType == WebEngineContextMenuData::MediaTypeAudio ||
- menuData.mediaType == WebEngineContextMenuData::MediaTypeVideo))
+ if (menuData.mediaUrl().isValid() &&
+ (menuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio ||
+ menuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo))
{
- QString urlString = menuData.mediaUrl.toString(QUrl::FullyEncoded);
+ QString urlString = menuData.mediaUrl().toString(QUrl::FullyEncoded);
QMimeData *data = new QMimeData();
data->setText(urlString);
- if (menuData.mediaType == WebEngineContextMenuData::MediaTypeAudio)
+ if (menuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio)
data->setHtml(QStringLiteral("<audio src=\"") + urlString + QStringLiteral("\"></audio>"));
else
data->setHtml(QStringLiteral("<video src=\"") + urlString + QStringLiteral("\"></video>"));
- data->setUrls(QList<QUrl>() << menuData.mediaUrl);
+ data->setUrls(QList<QUrl>() << menuData.mediaUrl());
qApp->clipboard()->setMimeData(data);
}
break;
case ToggleMediaControls:
- if (menuData.mediaUrl.isValid() && menuData.mediaFlags & WebEngineContextMenuData::MediaCanToggleControls) {
- bool enable = !(menuData.mediaFlags & WebEngineContextMenuData::MediaControls);
- d->adapter->executeMediaPlayerActionAt(menuData.pos, WebContentsAdapter::MediaPlayerControls, enable);
+ if (menuData.mediaUrl().isValid() && menuData.mediaFlags() & WebEngineContextMenuData::MediaCanToggleControls) {
+ bool enable = !(menuData.mediaFlags() & WebEngineContextMenuData::MediaControls);
+ d->adapter->executeMediaPlayerActionAt(menuData.position(), WebContentsAdapter::MediaPlayerControls, enable);
}
break;
case ToggleMediaLoop:
- if (menuData.mediaUrl.isValid() &&
- (menuData.mediaType == WebEngineContextMenuData::MediaTypeAudio ||
- menuData.mediaType == WebEngineContextMenuData::MediaTypeVideo))
+ if (menuData.mediaUrl().isValid() &&
+ (menuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio ||
+ menuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo))
{
- bool enable = !(menuData.mediaFlags & WebEngineContextMenuData::MediaLoop);
- d->adapter->executeMediaPlayerActionAt(menuData.pos, WebContentsAdapter::MediaPlayerLoop, enable);
+ bool enable = !(menuData.mediaFlags() & WebEngineContextMenuData::MediaLoop);
+ d->adapter->executeMediaPlayerActionAt(menuData.position(), WebContentsAdapter::MediaPlayerLoop, enable);
}
break;
case ToggleMediaPlayPause:
- if (menuData.mediaUrl.isValid() &&
- (menuData.mediaType == WebEngineContextMenuData::MediaTypeAudio ||
- menuData.mediaType == WebEngineContextMenuData::MediaTypeVideo))
+ if (menuData.mediaUrl().isValid() &&
+ (menuData.mediaType() == WebEngineContextMenuData::MediaTypeAudio ||
+ menuData.mediaType() == WebEngineContextMenuData::MediaTypeVideo))
{
- bool enable = (menuData.mediaFlags & WebEngineContextMenuData::MediaPaused);
- d->adapter->executeMediaPlayerActionAt(menuData.pos, WebContentsAdapter::MediaPlayerPlay, enable);
+ bool enable = (menuData.mediaFlags() & WebEngineContextMenuData::MediaPaused);
+ d->adapter->executeMediaPlayerActionAt(menuData.position(), WebContentsAdapter::MediaPlayerPlay, enable);
}
break;
case ToggleMediaMute:
- if (menuData.mediaUrl.isValid() && menuData.mediaFlags & WebEngineContextMenuData::MediaHasAudio) {
+ if (menuData.mediaUrl().isValid() && menuData.mediaFlags() & WebEngineContextMenuData::MediaHasAudio) {
// Make sure to negate the value, so that toggling actually works.
- bool enable = !(menuData.mediaFlags & WebEngineContextMenuData::MediaMuted);
- d->adapter->executeMediaPlayerActionAt(menuData.pos, WebContentsAdapter::MediaPlayerMute, enable);
+ bool enable = !(menuData.mediaFlags() & WebEngineContextMenuData::MediaMuted);
+ d->adapter->executeMediaPlayerActionAt(menuData.position(), WebContentsAdapter::MediaPlayerMute, enable);
}
break;
case InspectElement:
- d->adapter->inspectElementAt(menuData.pos);
+ d->adapter->inspectElementAt(menuData.position());
break;
case ExitFullScreen:
d->adapter->exitFullScreen();
@@ -1148,6 +1187,17 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
case SavePage:
d->adapter->save();
break;
+ case ViewSource:
+ // This is a workaround to make the ViewSource action working in a context menu.
+ // The WebContentsAdapter::viewSource() method deletes a
+ // RenderWidgetHostViewQtDelegateWidget instance which passes the control to the event
+ // loop. If the QMenu::aboutToHide() signal is connected to the QObject::deleteLater()
+ // slot the QMenu is deleted by the event handler while the ViewSource action is still not
+ // completed. This may lead to a crash. To avoid this the WebContentsAdapter::viewSource()
+ // method is called indirectly via the QTimer::singleShot() function which schedules the
+ // the viewSource() call after the QMenu's destruction.
+ QTimer::singleShot(0, this, [d](){ d->adapter->viewSource(); });
+ break;
case NoWebAction:
break;
case WebActionCount:
@@ -1156,6 +1206,22 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
}
}
+/*!
+ * \since 5.8
+ * Replace the current misspelled word with \a replacement.
+ *
+ * The current misspelled word can be found in QWebEngineContextMenuData::misspelledWord(),
+ * and suggested replacements in QWebEngineContextMenuData::spellCheckerSuggestions().
+ *
+ * \sa contextMenuData(),
+ */
+
+void QWebEnginePage::replaceMisspelledWord(const QString &replacement)
+{
+ Q_D(QWebEnginePage);
+ d->adapter->replaceMisspelling(replacement);
+}
+
void QWebEnginePage::findText(const QString &subString, FindFlags options, const QWebEngineCallback<bool> &resultCallback)
{
Q_D(QWebEnginePage);
@@ -1192,7 +1258,7 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData
return false;
contextData.reset();
- QContextMenuEvent event(QContextMenuEvent::Mouse, data.pos, view->mapToGlobal(data.pos));
+ QContextMenuEvent event(QContextMenuEvent::Mouse, data.position(), view->mapToGlobal(data.position()));
switch (view->contextMenuPolicy()) {
case Qt::PreventContextMenu:
return false;
@@ -1202,7 +1268,7 @@ bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData
break;
case Qt::CustomContextMenu:
contextData = data;
- Q_EMIT view->customContextMenuRequested(data.pos);
+ Q_EMIT view->customContextMenuRequested(data.position());
break;
case Qt::ActionsContextMenu:
if (view->actions().count()) {
@@ -1337,6 +1403,16 @@ bool QWebEnginePagePrivate::isEnabled() const
return true;
}
+void QWebEnginePagePrivate::setToolTip(const QString &toolTipText)
+{
+ if (view) {
+ QString wrappedTip;
+ if (!toolTipText.isEmpty())
+ wrappedTip = QLatin1String("<p>") % toolTipText.toHtmlEscaped().left(MaxTooltipLength) % QLatin1String("</p>");
+ view->setToolTip(wrappedTip);
+ }
+}
+
QMenu *QWebEnginePage::createStandardContextMenu()
{
Q_D(QWebEnginePage);
@@ -1347,13 +1423,25 @@ QMenu *QWebEnginePage::createStandardContextMenu()
QAction *action = 0;
const WebEngineContextMenuData &contextMenuData = *d->contextData.d;
- if (!contextMenuData.linkText.isEmpty() && contextMenuData.linkUrl.isValid()) {
+ if (contextMenuData.isEditable() && !contextMenuData.spellCheckerSuggestions().isEmpty()) {
+ QPointer<QWebEnginePage> thisRef(this);
+ for (int i=0; i < contextMenuData.spellCheckerSuggestions().count() && i < 4; i++) {
+ QAction *action = new QAction(menu);
+ QString replacement = contextMenuData.spellCheckerSuggestions().at(i);
+ QObject::connect(action, &QAction::triggered, [thisRef, replacement] { if (thisRef) thisRef->replaceMisspelledWord(replacement); });
+ action->setText(replacement);
+ menu->addAction(action);
+ }
+ menu->addSeparator();
+ }
+
+ if (!contextMenuData.linkText().isEmpty() && contextMenuData.linkUrl().isValid()) {
action = QWebEnginePage::action(OpenLinkInThisWindow);
action->setText(tr("Follow Link"));
menu->addAction(action);
menu->addAction(QWebEnginePage::action(DownloadLinkToDisk));
}
- if (contextMenuData.selectedText.isEmpty()) {
+ if (contextMenuData.selectedText().isEmpty()) {
action = new QAction(QIcon::fromTheme(QStringLiteral("go-previous")), tr("&Back"), menu);
connect(action, &QAction::triggered, d->view, &QWebEngineView::back);
action->setEnabled(d->adapter->canGoBack());
@@ -1367,16 +1455,18 @@ QMenu *QWebEnginePage::createStandardContextMenu()
action = new QAction(QIcon::fromTheme(QStringLiteral("view-refresh")), tr("&Reload"), menu);
connect(action, &QAction::triggered, d->view, &QWebEngineView::reload);
menu->addAction(action);
+
+ menu->addAction(QWebEnginePage::action(ViewSource));
} else {
menu->addAction(QWebEnginePage::action(Copy));
menu->addAction(QWebEnginePage::action(Unselect));
}
- if (!contextMenuData.linkText.isEmpty() && contextMenuData.linkUrl.isValid()) {
+ if (!contextMenuData.linkText().isEmpty() && contextMenuData.linkUrl().isValid()) {
menu->addAction(QWebEnginePage::action(CopyLinkToClipboard));
}
- if (contextMenuData.mediaUrl.isValid()) {
- switch (contextMenuData.mediaType) {
+ if (contextMenuData.mediaUrl().isValid()) {
+ switch (contextMenuData.mediaType()) {
case WebEngineContextMenuData::MediaTypeImage:
menu->addAction(QWebEnginePage::action(DownloadImageToDisk));
menu->addAction(QWebEnginePage::action(CopyImageUrlToClipboard));
@@ -1391,15 +1481,15 @@ QMenu *QWebEnginePage::createStandardContextMenu()
menu->addAction(QWebEnginePage::action(CopyMediaUrlToClipboard));
menu->addAction(QWebEnginePage::action(ToggleMediaPlayPause));
menu->addAction(QWebEnginePage::action(ToggleMediaLoop));
- if (contextMenuData.mediaFlags & WebEngineContextMenuData::MediaHasAudio)
+ if (contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaHasAudio)
menu->addAction(QWebEnginePage::action(ToggleMediaMute));
- if (contextMenuData.mediaFlags & WebEngineContextMenuData::MediaCanToggleControls)
+ if (contextMenuData.mediaFlags() & WebEngineContextMenuData::MediaCanToggleControls)
menu->addAction(QWebEnginePage::action(ToggleMediaControls));
break;
default:
break;
}
- } else if (contextMenuData.mediaType == WebEngineContextMenuData::MediaTypeCanvas) {
+ } else if (contextMenuData.mediaType() == WebEngineContextMenuData::MediaTypeCanvas) {
menu->addAction(QWebEnginePage::action(CopyImageToClipboard));
}
@@ -1457,7 +1547,7 @@ static inline QWebEnginePage::FileSelectionMode toPublic(FilePickerController::F
return static_cast<QWebEnginePage::FileSelectionMode>(mode);
}
-void QWebEnginePagePrivate::runFileChooser(FilePickerController *controller)
+void QWebEnginePagePrivate::runFileChooser(QSharedPointer<FilePickerController> controller)
{
Q_Q(QWebEnginePage);
@@ -1763,6 +1853,28 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res
d->m_callbacks.registerCallback(requestId, resultCallback);
}
+#ifndef QT_NO_PRINTER
+/*!
+ \fn void QWebEnginePage::print(const QPrinter &printer, FunctorOrLambda resultCallback)
+ Renders the current content of the page into a temporary PDF document, then prints it using \a printer.
+
+ The settings for creating and printing the PDF document will be retrieved from the \a printer
+ object.
+ It is the users responsibility to ensure the \a printer remains valid until \a resultCallback
+ has been called.
+
+ 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.
+ \since 5.8
+*/
+void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback)
+{
+ Q_D(QWebEnginePage);
+ quint64 requestId = d->adapter->printOnPrinterCallbackResult(printer);
+ d->m_callbacks.registerCallback(requestId, resultCallback);
+}
+#endif // QT_NO_PRINTER
+
/*!
\since 5.7
@@ -1777,6 +1889,31 @@ const QWebEngineContextMenuData &QWebEnginePage::contextMenuData() const
return d->contextData;
}
+/*!
+ \since 5.8
+
+ Shows the source of the current page in a new tab.
+
+ \sa canViewSource
+*/
+void QWebEnginePage::viewSource()
+{
+ triggerAction(QWebEnginePage::ViewSource);
+}
+
+/*!
+ \property QWebEnginePage::canViewSource
+ \brief whether the source for the current page can be viewed.
+ \since 5.8
+
+ \sa viewSource()
+*/
+bool QWebEnginePage::canViewSource() const
+{
+ Q_D(const QWebEnginePage);
+ return d->adapter->canViewSource();
+}
+
QT_END_NAMESPACE
#include "moc_qwebenginepage.cpp"
diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h
index 2ac8e0f3e..923c3bb70 100644
--- a/src/webenginewidgets/api/qwebenginepage.h
+++ b/src/webenginewidgets/api/qwebenginepage.h
@@ -42,6 +42,7 @@
#include <QtWebEngineWidgets/qtwebenginewidgetsglobal.h>
#include <QtWebEngineWidgets/qwebenginecertificateerror.h>
+#include <QtWebEngineWidgets/qwebenginedownloaditem.h>
#include <QtWebEngineCore/qwebenginecallback.h>
#include <QtCore/qobject.h>
@@ -53,6 +54,9 @@
QT_BEGIN_NAMESPACE
class QMenu;
+#ifndef QT_NO_PRINTER
+class QPrinter;
+#endif
class QWebChannel;
class QWebEngineContextMenuData;
class QWebEngineFullScreenRequest;
@@ -80,6 +84,7 @@ class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject {
Q_PROPERTY(QPointF scrollPosition READ scrollPosition NOTIFY scrollPositionChanged)
Q_PROPERTY(bool audioMuted READ isAudioMuted WRITE setAudioMuted NOTIFY audioMutedChanged)
Q_PROPERTY(bool recentlyAudible READ recentlyAudible NOTIFY recentlyAudibleChanged)
+ Q_PROPERTY(bool canViewSource READ canViewSource)
public:
enum WebAction {
@@ -123,6 +128,7 @@ public:
Unselect,
SavePage,
OpenLinkInNewBackgroundTab,
+ ViewSource,
WebActionCount
};
@@ -206,6 +212,8 @@ public:
#endif
virtual void triggerAction(WebAction action, bool checked = false);
+ void replaceMisspelledWord(const QString &replacement);
+
virtual bool event(QEvent*);
#ifdef Q_QDOC
void findText(const QString &subString, FindFlags options = FindFlags());
@@ -261,6 +269,9 @@ public:
QColor backgroundColor() const;
void setBackgroundColor(const QColor &color);
+ void save(const QString &filePath, QWebEngineDownloadItem::SavePageFormat format
+ = QWebEngineDownloadItem::MimeHtmlSaveFormat) const;
+
bool isAudioMuted() const;
void setAudioMuted(bool muted);
bool recentlyAudible() const;
@@ -272,7 +283,17 @@ public:
void printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &layout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()));
#endif
+#ifndef QT_NO_PRINTER
+#ifdef Q_QDOC
+ void print(QPrinter *printer, FunctorOrLambda resultCallback)
+#else
+ void print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback);
+#endif // QDOC
+#endif // QT_NO_PRINTER
+
const QWebEngineContextMenuData &contextMenuData() const;
+ void viewSource();
+ bool canViewSource() const;
Q_SIGNALS:
void loadStarted();
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 96640a63a..8d78429d8 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -112,13 +112,16 @@ public:
virtual void requestFullScreenMode(const QUrl &origin, bool fullscreen) Q_DECL_OVERRIDE;
virtual bool isFullScreenMode() const Q_DECL_OVERRIDE;
virtual void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) Q_DECL_OVERRIDE;
- virtual void runFileChooser(QtWebEngineCore::FilePickerController *controller) Q_DECL_OVERRIDE;
+ virtual void runFileChooser(QSharedPointer<QtWebEngineCore::FilePickerController>) Q_DECL_OVERRIDE;
virtual void showColorDialog(QSharedPointer<QtWebEngineCore::ColorChooserController>) Q_DECL_OVERRIDE;
virtual void didRunJavaScript(quint64 requestId, const QVariant& result) Q_DECL_OVERRIDE;
virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) Q_DECL_OVERRIDE;
virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) Q_DECL_OVERRIDE;
virtual void didFindText(quint64 requestId, int matchCount) Q_DECL_OVERRIDE;
virtual void didPrintPage(quint64 requestId, const QByteArray &result) Q_DECL_OVERRIDE;
+#ifndef QT_NO_PRINTER
+ virtual void didPrintPageOnPrinter(quint64 requestId, bool result) Q_DECL_OVERRIDE;
+#endif
virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE;
virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE;
virtual void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) Q_DECL_OVERRIDE;
@@ -141,6 +144,7 @@ public:
void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions,
const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE;
virtual bool isEnabled() const Q_DECL_OVERRIDE;
+ virtual void setToolTip(const QString &toolTipText) Q_DECL_OVERRIDE;
const QObject *holdingQObject() const Q_DECL_OVERRIDE;
virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE;
@@ -173,6 +177,7 @@ public:
QWebChannel *webChannel;
unsigned int webChannelWorldId;
QUrl iconUrl;
+ bool m_navigationActionTriggered;
mutable QtWebEngineCore::CallbackDirectory m_callbacks;
mutable QAction *actions[QWebEnginePage::WebActionCount];
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index 664323034..a400b5792 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -96,6 +96,11 @@ using QtWebEngineCore::BrowserContextAdapter;
A QWebEngineUrlSchemeHandler can be registered for a profile by installUrlSchemeHandler()
to add support for custom URL schemes. Requests for the scheme are then issued to
QWebEngineUrlSchemeHandler::requestStarted() as QWebEngineUrlRequestJob objects.
+
+ Spellchecking HTML form fields can be enabled per profile by using the setSpellCheckEnabled()
+ method and the current language used for spellchecking can be set by using the
+ setSpellCheckLanguage() method.
+
*/
/*!
@@ -180,10 +185,12 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
Q_ASSERT(!m_ongoingDownloads.contains(info.id));
QWebEngineDownloadItemPrivate *itemPrivate = new QWebEngineDownloadItemPrivate(this, info.url);
itemPrivate->downloadId = info.id;
- itemPrivate->downloadState = QWebEngineDownloadItem::DownloadRequested;
+ itemPrivate->downloadState = info.accepted ? QWebEngineDownloadItem::DownloadInProgress
+ : QWebEngineDownloadItem::DownloadRequested;
itemPrivate->downloadPath = info.path;
itemPrivate->mimeType = info.mimeType;
itemPrivate->savePageFormat = static_cast<QWebEngineDownloadItem::SavePageFormat>(info.savePageFormat);
+ itemPrivate->type = static_cast<QWebEngineDownloadItem::DownloadType>(info.downloadType);
QWebEngineDownloadItem *download = new QWebEngineDownloadItem(itemPrivate, q);
@@ -556,6 +563,67 @@ QWebEngineProfile *QWebEngineProfile::defaultProfile()
}
/*!
+ \since 5.8
+
+ Sets the current \a language for the spell checker.
+ The language should match the name of the \c .bdic dictionary.
+ For example, the \a language \c en-US will load the \c en-US.bdic
+ dictionary file.
+
+ The web engine checks for the \c qtwebengine_dictionaries subdirectory
+ first in the local directory and if it is not found in the Qt
+ installation directory:
+
+ \list
+ \li QCoreApplication::applicationDirPath()/qtwebengine_dictionaries
+ \li [QLibraryInfo::DataPath]/qtwebengine_dictionaries
+ \endlist
+
+ For more information about how to compile \c .bdic dictionaries, see the
+ \l{WebEngine Widgets Spellchecker Example}{Spellchecker Example}.
+
+*/
+void QWebEngineProfile::setSpellCheckLanguage(const QString &language)
+{
+ Q_D(QWebEngineProfile);
+ d->browserContext()->setSpellCheckLanguage(language);
+}
+
+/*!
+ \since 5.8
+
+ Returns the language used by the spell checker.
+*/
+QString QWebEngineProfile::spellCheckLanguage() const
+{
+ const Q_D(QWebEngineProfile);
+ return d->browserContext()->spellCheckLanguage();
+}
+
+/*!
+ \since 5.8
+
+ Enables spell checker if \a enable is \c true, otherwise disables it.
+ \sa isSpellCheckEnabled()
+ */
+void QWebEngineProfile::setSpellCheckEnabled(bool enable)
+{
+ Q_D(QWebEngineProfile);
+ d->browserContext()->setSpellCheckEnabled(enable);
+}
+/*!
+ \since 5.8
+
+ Returns \c true if the spell checker is enabled; otherwise returns \c false.
+ \sa setSpellCheckEnabled()
+ */
+bool QWebEngineProfile::isSpellCheckEnabled() const
+{
+ const Q_D(QWebEngineProfile);
+ return d->browserContext()->isSpellCheckEnabled();
+}
+
+/*!
Returns the default settings for all pages in this profile.
*/
QWebEngineSettings *QWebEngineProfile::settings() const
diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h
index d981fa5bb..704414bcf 100644
--- a/src/webenginewidgets/api/qwebengineprofile.h
+++ b/src/webenginewidgets/api/qwebengineprofile.h
@@ -121,6 +121,11 @@ public:
void clearHttpCache();
+ void setSpellCheckLanguage(const QString &language);
+ QString spellCheckLanguage() const;
+ void setSpellCheckEnabled(bool enabled);
+ bool isSpellCheckEnabled() const;
+
static QWebEngineProfile *defaultProfile();
Q_SIGNALS:
diff --git a/src/webenginewidgets/api/qwebenginescript.cpp b/src/webenginewidgets/api/qwebenginescript.cpp
index 73dd5075e..b434126bc 100644
--- a/src/webenginewidgets/api/qwebenginescript.cpp
+++ b/src/webenginewidgets/api/qwebenginescript.cpp
@@ -61,7 +61,8 @@ using QtWebEngineCore::UserScript;
not accessible from a different one. ScriptWorldId provides some predefined IDs for this
purpose.
- \note Chromium extensions, such as \c @include, \c @match, and \c @exclude, are not supported.
+ The following Chromium extensions are supported since Qt 5.8: \c @exclude, \c @include,
+ \c @name, \c @match, and \c @run-at.
Use QWebEnginePage::scripts() and QWebEngineProfile::scripts() to access
the collection of scripts associated with a single page or a
diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp
index dfca16287..f14aa9352 100644
--- a/src/webenginewidgets/api/qwebenginesettings.cpp
+++ b/src/webenginewidgets/api/qwebenginesettings.cpp
@@ -89,6 +89,11 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web
return WebEngineSettings::AutoLoadIconsForPage;
case QWebEngineSettings::TouchIconsEnabled:
return WebEngineSettings::TouchIconsEnabled;
+ case QWebEngineSettings::FocusOnNavigationEnabled:
+ return WebEngineSettings::FocusOnNavigationEnabled;
+ case QWebEngineSettings::PrintElementBackgrounds:
+ return WebEngineSettings::PrintElementBackgrounds;
+
default:
return WebEngineSettings::UnsupportedInCoreSettings;
}
diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h
index 8eda50ee2..23a1d5c99 100644
--- a/src/webenginewidgets/api/qwebenginesettings.h
+++ b/src/webenginewidgets/api/qwebenginesettings.h
@@ -85,7 +85,9 @@ public:
WebGLEnabled,
Accelerated2dCanvasEnabled,
AutoLoadIconsForPage,
- TouchIconsEnabled
+ TouchIconsEnabled,
+ FocusOnNavigationEnabled,
+ PrintElementBackgrounds
};
enum FontSize {
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index 539e809d4..560d4a2e4 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -87,6 +87,10 @@
QWebEngineScript::ScriptWorldId provides some predefined IDs for this purpose. Using the
\c runJavaScript() version without the world ID is the same as running the script in the
\c MainWorld.
+
+ The \l {QWebEngineSettings::FocusOnNavigationEnabled} {FocusOnNavigationEnabled} setting can be
+ used to stop the view associated with the page from automatically receiving focus when a
+ navigation operation occurs (like loading or reloading a page or navigating through history).
*/
/*!
@@ -152,6 +156,7 @@
\value Unselect Clear the current selection. (Added in Qt 5.7)
\value SavePage Save the current page to disk. MHTML is the default format that is used to store
the web page on disk. (Added in Qt 5.7)
+ \value ViewSource Shows the source of the current page in a new tab. (Added in Qt 5.8)
\omitvalue WebActionCount
diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
index ccb002404..955f6d80b 100644
--- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
@@ -147,6 +147,14 @@
\value TouchIconsEnabled
Enables support for touch icons and precomposed touch icons
Disabled by default. (Added in Qt 5.7)
+ \value FocusOnNavigationEnabled
+ Gives focus to the view associated with the page, whenever a navigation operation occurs
+ (load, stop, reload, reload and bypass cache, forward, backward, set content, and so
+ on).
+ Enabled by default. (Added in Qt 5.8)
+ \value PrintElementBackgrounds
+ Turns on printing of CSS backgrounds when printing a web page.
+ Enabled by default. (Added in Qt 5.8)
*/
/*!
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 28c40fed5..9b5d90146 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -49,20 +49,51 @@
#include <QSGAbstractRenderer>
#include <QSGNode>
#include <QWindow>
-#include <private/qsgcontext_p.h>
-#include <private/qsgengine_p.h>
+#include <private/qquickwindow_p.h>
+
+#if (QT_VERSION < QT_VERSION_CHECK(5, 8, 0))
+#include <QSGSimpleRectNode>
+#include <QSGSimpleTextureNode>
+#endif
namespace QtWebEngineCore {
-static const int MaxTooltipLength = 1024;
+class RenderWidgetHostViewQuickItem : public QQuickItem {
+public:
+ RenderWidgetHostViewQuickItem(RenderWidgetHostViewQtDelegateClient *client) : m_client(client)
+ {
+ setFlag(ItemHasContents, true);
+ }
+protected:
+ void focusInEvent(QFocusEvent *event) override
+ {
+ m_client->forwardEvent(event);
+ }
+ void focusOutEvent(QFocusEvent *event) override
+ {
+ m_client->forwardEvent(event);
+ }
+ void keyPressEvent(QKeyEvent *event) override
+ {
+ m_client->forwardEvent(event);
+ }
+ void keyReleaseEvent(QKeyEvent *event) override
+ {
+ m_client->forwardEvent(event);
+ }
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) override
+ {
+ return m_client->updatePaintNode(oldNode);
+ }
+private:
+ RenderWidgetHostViewQtDelegateClient *m_client;
+};
RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(RenderWidgetHostViewQtDelegateClient *client, QWidget *parent)
- : QOpenGLWidget(parent)
+ : QQuickWidget(parent)
, m_client(client)
- , m_rootNode(new QSGRootNode)
- , m_sgEngine(new QSGEngine)
+ , m_rootItem(new RenderWidgetHostViewQuickItem(client))
, m_isPopup(false)
- , m_clearColor(Qt::white)
{
setFocusPolicy(Qt::StrongFocus);
@@ -90,7 +121,7 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende
}
#endif
- // Make sure the OpenGL profile of the QOpenGLWidget matches the shared context profile.
+ // Make sure the OpenGL profile of the QQuickWidget matches the shared context profile.
if (sharedFormat.profile() == QSurfaceFormat::CoreProfile) {
format.setMajorVersion(sharedFormat.majorVersion());
format.setMinorVersion(sharedFormat.minorVersion());
@@ -109,6 +140,8 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende
void RenderWidgetHostViewQtDelegateWidget::initAsChild(WebContentsAdapterClient* container)
{
+ setContent(QUrl(), nullptr, m_rootItem.data());
+
QWebEnginePagePrivate *pagePrivate = static_cast<QWebEnginePagePrivate *>(container);
if (pagePrivate->view) {
pagePrivate->view->layout()->addWidget(this);
@@ -121,6 +154,8 @@ void RenderWidgetHostViewQtDelegateWidget::initAsChild(WebContentsAdapterClient*
void RenderWidgetHostViewQtDelegateWidget::initAsPopup(const QRect& screenRect)
{
m_isPopup = true;
+ setContent(QUrl(), nullptr, m_rootItem.data());
+
// The keyboard events are supposed to go to the parent RenderHostView
// so the WebUI popups should never have focus. Besides, if the parent view
// loses focus, WebKit will cause its associated popups (including this one)
@@ -146,12 +181,12 @@ QRectF RenderWidgetHostViewQtDelegateWidget::contentsRect() const
void RenderWidgetHostViewQtDelegateWidget::setKeyboardFocus()
{
- setFocus();
+ m_rootItem->forceActiveFocus();
}
bool RenderWidgetHostViewQtDelegateWidget::hasKeyboardFocus()
{
- return hasFocus();
+ return m_rootItem->hasActiveFocus();
}
void RenderWidgetHostViewQtDelegateWidget::lockMouse()
@@ -169,65 +204,85 @@ void RenderWidgetHostViewQtDelegateWidget::show()
// Check if we're attached to a QWebEngineView, we don't
// want to show anything else than popups as top-level.
if (parent() || m_isPopup) {
- QOpenGLWidget::show();
+ QQuickWidget::show();
}
}
void RenderWidgetHostViewQtDelegateWidget::hide()
{
- QOpenGLWidget::hide();
+ QQuickWidget::hide();
}
bool RenderWidgetHostViewQtDelegateWidget::isVisible() const
{
- return QOpenGLWidget::isVisible();
+ return QQuickWidget::isVisible();
}
QWindow* RenderWidgetHostViewQtDelegateWidget::window() const
{
- const QWidget* root = QOpenGLWidget::window();
+ const QWidget* root = QQuickWidget::window();
return root ? root->windowHandle() : 0;
}
QSGTexture *RenderWidgetHostViewQtDelegateWidget::createTextureFromImage(const QImage &image)
{
- return m_sgEngine->createTextureFromImage(image, QSGEngine::TextureCanUseAtlas);
+ return quickWindow()->createTextureFromImage(image, QQuickWindow::TextureCanUseAtlas);
}
QSGLayer *RenderWidgetHostViewQtDelegateWidget::createLayer()
{
- QSGEnginePrivate *enginePrivate = QSGEnginePrivate::get(m_sgEngine.data());
- return enginePrivate->sgContext->createLayer(enginePrivate->sgRenderContext.data());
+ QSGRenderContext *renderContext = QQuickWindowPrivate::get(quickWindow())->context;
+ return renderContext->sceneGraphContext()->createLayer(renderContext);
}
-QSGImageNode *RenderWidgetHostViewQtDelegateWidget::createImageNode()
+QSGInternalImageNode *RenderWidgetHostViewQtDelegateWidget::createImageNode()
{
- return QSGEnginePrivate::get(m_sgEngine.data())->sgContext->createImageNode();
+ QSGRenderContext *renderContext = QQuickWindowPrivate::get(quickWindow())->context;
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
+ return renderContext->sceneGraphContext()->createInternalImageNode();
+#else
+ return renderContext->sceneGraphContext()->createImageNode();
+#endif
}
-void RenderWidgetHostViewQtDelegateWidget::update()
+QSGTextureNode *RenderWidgetHostViewQtDelegateWidget::createTextureNode()
{
-#if (QT_VERSION < QT_VERSION_CHECK(5, 4, 0))
- updateGL();
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
+ return quickWindow()->createImageNode();
#else
- QOpenGLWidget::update();
+ return new QSGSimpleTextureNode();
#endif
}
+QSGRectangleNode *RenderWidgetHostViewQtDelegateWidget::createRectangleNode()
+{
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
+ return quickWindow()->createRectangleNode();
+#else
+ QSGRenderContext *renderContext = QQuickWindowPrivate::get(quickWindow())->context;
+ return renderContext->sceneGraphContext()->createRectangleNode();
+#endif
+}
+
+void RenderWidgetHostViewQtDelegateWidget::update()
+{
+ m_rootItem->update();
+}
+
void RenderWidgetHostViewQtDelegateWidget::updateCursor(const QCursor &cursor)
{
- QOpenGLWidget::setCursor(cursor);
+ QQuickWidget::setCursor(cursor);
}
void RenderWidgetHostViewQtDelegateWidget::resize(int width, int height)
{
- QOpenGLWidget::resize(width, height);
+ QQuickWidget::resize(width, height);
}
void RenderWidgetHostViewQtDelegateWidget::move(const QPoint &screenPos)
{
Q_ASSERT(m_isPopup);
- QOpenGLWidget::move(screenPos);
+ QQuickWidget::move(screenPos);
}
void RenderWidgetHostViewQtDelegateWidget::inputMethodStateChanged(bool editorVisible)
@@ -235,23 +290,15 @@ void RenderWidgetHostViewQtDelegateWidget::inputMethodStateChanged(bool editorVi
if (qApp->inputMethod()->isVisible() == editorVisible)
return;
- QOpenGLWidget::setAttribute(Qt::WA_InputMethodEnabled, editorVisible);
+ QQuickWidget::setAttribute(Qt::WA_InputMethodEnabled, editorVisible);
qApp->inputMethod()->update(Qt::ImQueryInput | Qt::ImEnabled | Qt::ImHints);
qApp->inputMethod()->setVisible(editorVisible);
}
-void RenderWidgetHostViewQtDelegateWidget::setTooltip(const QString &tooltip)
-{
- QString wrappedTip;
- if (!tooltip.isEmpty())
- wrappedTip = QLatin1String("<p>") % tooltip.toHtmlEscaped().left(MaxTooltipLength) % QLatin1String("</p>");
- setToolTip(wrappedTip);
-}
-
void RenderWidgetHostViewQtDelegateWidget::setClearColor(const QColor &color)
{
- m_clearColor = color;
- // QOpenGLWidget is usually blended by punching holes into widgets
+ QQuickWidget::setClearColor(color);
+ // QQuickWidget is usually blended by punching holes into widgets
// above it to simulate the visual stacking order. If we want it to be
// transparent we have to throw away the proper stacking order and always
// blend the complete normal widgets backing store under it.
@@ -268,7 +315,7 @@ QVariant RenderWidgetHostViewQtDelegateWidget::inputMethodQuery(Qt::InputMethodQ
void RenderWidgetHostViewQtDelegateWidget::resizeEvent(QResizeEvent *resizeEvent)
{
- QOpenGLWidget::resizeEvent(resizeEvent);
+ QQuickWidget::resizeEvent(resizeEvent);
const QPoint globalPos = mapToGlobal(pos());
if (globalPos != m_lastGlobalPos) {
@@ -281,7 +328,7 @@ void RenderWidgetHostViewQtDelegateWidget::resizeEvent(QResizeEvent *resizeEvent
void RenderWidgetHostViewQtDelegateWidget::showEvent(QShowEvent *event)
{
- QOpenGLWidget::showEvent(event);
+ QQuickWidget::showEvent(event);
// We don't have a way to catch a top-level window change with QWidget
// but a widget will most likely be shown again if it changes, so do
// the reconnection at this point.
@@ -298,7 +345,7 @@ void RenderWidgetHostViewQtDelegateWidget::showEvent(QShowEvent *event)
void RenderWidgetHostViewQtDelegateWidget::hideEvent(QHideEvent *event)
{
- QOpenGLWidget::hideEvent(event);
+ QQuickWidget::hideEvent(event);
m_client->notifyHidden();
}
@@ -333,11 +380,19 @@ bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event)
}
}
- if (event->type() == QEvent::ShortcutOverride) {
+ switch (event->type()) {
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ // We forward focus events later, once they have made it to the m_rootItem.
+ return QQuickWidget::event(event);
+ case QEvent::ShortcutOverride:
if (editorActionForKeyEvent(static_cast<QKeyEvent*>(event)) != QWebEnginePage::NoWebAction) {
event->accept();
return true;
}
+ break;
+ default:
+ break;
}
if (event->type() == QEvent::MouseButtonDblClick) {
@@ -353,45 +408,10 @@ bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event)
handled = m_client->forwardEvent(event);
if (!handled)
- return QOpenGLWidget::event(event);
+ return QQuickWidget::event(event);
return true;
}
-void RenderWidgetHostViewQtDelegateWidget::initializeGL()
-{
- m_sgEngine->initialize(QOpenGLContext::currentContext());
- m_sgRenderer.reset(m_sgEngine->createRenderer());
- m_sgRenderer->setRootNode(m_rootNode.data());
- m_sgRenderer->setClearColor(m_clearColor);
-
- // When RenderWidgetHostViewQt::GetScreenInfo is called for the first time, the associated
- // QWindow is NULL, and the screen device pixel ratio can not be queried.
- // Re-initialize the screen information after the QWindow handle is available,
- // so Chromium receives the correct device pixel ratio.
- m_client->windowChanged();
-}
-
-void RenderWidgetHostViewQtDelegateWidget::paintGL()
-{
-#if (QT_VERSION < QT_VERSION_CHECK(5, 3, 1))
- // A workaround for a missing check in 5.3.0 when updating an unparented delegate.
- if (!QOpenGLContext::currentContext())
- return;
-#endif
- QSGNode *paintNode = m_client->updatePaintNode(m_rootNode->firstChild());
- if (paintNode != m_rootNode->firstChild()) {
- delete m_rootNode->firstChild();
- m_rootNode->appendChildNode(paintNode);
- }
-
- QSize deviceSize = size() * devicePixelRatio();
- m_sgRenderer->setDeviceRect(deviceSize);
- m_sgRenderer->setViewportRect(deviceSize);
- m_sgRenderer->setProjectionMatrixToRect(QRectF(QPointF(), size()));
-
- m_sgRenderer->renderScene(defaultFramebufferObject());
-}
-
void RenderWidgetHostViewQtDelegateWidget::onWindowPosChanged()
{
m_lastGlobalPos = mapToGlobal(pos());
diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
index 7307bcd55..77907ec5a 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
@@ -43,19 +43,12 @@
#include "render_widget_host_view_qt_delegate.h"
#include "web_contents_adapter_client.h"
-#include <QSGAbstractRenderer>
-#include <QSGEngine>
-#include <QSGNode>
-
-#if (QT_VERSION < QT_VERSION_CHECK(5, 4, 0))
-#include <QtWidgets/private/qopenglwidget_p.h>
-#else
-#include <QtWidgets/QOpenGLWidget>
-#endif
+#include <QQuickItem>
+#include <QQuickWidget>
namespace QtWebEngineCore {
-class RenderWidgetHostViewQtDelegateWidget : public QOpenGLWidget, public RenderWidgetHostViewQtDelegate {
+class RenderWidgetHostViewQtDelegateWidget : public QQuickWidget, public RenderWidgetHostViewQtDelegate {
Q_OBJECT
public:
RenderWidgetHostViewQtDelegateWidget(RenderWidgetHostViewQtDelegateClient *client, QWidget *parent = 0);
@@ -74,13 +67,14 @@ public:
virtual QWindow* window() const Q_DECL_OVERRIDE;
virtual QSGTexture *createTextureFromImage(const QImage &) Q_DECL_OVERRIDE;
virtual QSGLayer *createLayer() Q_DECL_OVERRIDE;
- virtual QSGImageNode *createImageNode() Q_DECL_OVERRIDE;
+ virtual QSGInternalImageNode *createImageNode() Q_DECL_OVERRIDE;
+ virtual QSGTextureNode *createTextureNode() Q_DECL_OVERRIDE;
+ virtual QSGRectangleNode *createRectangleNode() Q_DECL_OVERRIDE;
virtual void update() Q_DECL_OVERRIDE;
virtual void updateCursor(const QCursor &) Q_DECL_OVERRIDE;
virtual void resize(int width, int height) Q_DECL_OVERRIDE;
virtual void move(const QPoint &screenPos) Q_DECL_OVERRIDE;
virtual void inputMethodStateChanged(bool editorVisible) Q_DECL_OVERRIDE;
- virtual void setTooltip(const QString &tooltip) Q_DECL_OVERRIDE;
virtual void setClearColor(const QColor &color) Q_DECL_OVERRIDE;
protected:
@@ -88,8 +82,6 @@ protected:
void resizeEvent(QResizeEvent *resizeEvent) Q_DECL_OVERRIDE;
void showEvent(QShowEvent *) Q_DECL_OVERRIDE;
void hideEvent(QHideEvent *) Q_DECL_OVERRIDE;
- void initializeGL() Q_DECL_OVERRIDE;
- void paintGL() Q_DECL_OVERRIDE;
QVariant inputMethodQuery(Qt::InputMethodQuery query) const Q_DECL_OVERRIDE;
@@ -98,10 +90,7 @@ private slots:
private:
RenderWidgetHostViewQtDelegateClient *m_client;
- // Put the root node first to make sure it gets destroyed after the SG renderer.
- QScopedPointer<QSGRootNode> m_rootNode;
- QScopedPointer<QSGEngine> m_sgEngine;
- QScopedPointer<QSGAbstractRenderer> m_sgRenderer;
+ QScopedPointer<QQuickItem> m_rootItem;
bool m_isPopup;
QColor m_clearColor;
QPoint m_lastGlobalPos;
diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro
index cd9a2d10b..f1bb86df4 100644
--- a/src/webenginewidgets/webenginewidgets.pro
+++ b/src/webenginewidgets/webenginewidgets.pro
@@ -4,7 +4,7 @@ TARGET = QtWebEngineWidgets
DEFINES += QT_BUILD_WEBENGINEWIDGETS_LIB
QT += webenginecore widgets network quick
-QT_PRIVATE += quick-private gui-private core-private
+QT_PRIVATE += quick-private gui-private core-private quickwidgets
INCLUDEPATH += $$PWD api ../core ../core/api ../webengine/api
diff --git a/sync.profile b/sync.profile
index e4a88e0c2..e713faee4 100644
--- a/sync.profile
+++ b/sync.profile
@@ -24,5 +24,6 @@
"qttools" => "",
# FIXME: take examples out into their own module to avoid a potential circular dependency later ?
"qtquickcontrols" => "",
+ "qtquickcontrols2" => "",
"qtwebchannel" => "",
);
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index 1937dca04..f9fd854cc 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -36,6 +36,7 @@
#include <QtWebEngine/QQuickWebEngineProfile>
#include <private/qquickwebengineview_p.h>
#include <private/qquickwebenginecertificateerror_p.h>
+#include <private/qquickwebenginedialogrequests_p.h>
#include <private/qquickwebenginedownloaditem_p.h>
#include <private/qquickwebenginehistory_p.h>
#include <private/qquickwebengineloadrequest_p.h>
@@ -44,6 +45,7 @@
#include <private/qquickwebenginescript_p.h>
#include <private/qquickwebenginesettings_p.h>
#include <private/qquickwebenginesingleton_p.h>
+#include <private/qquickwebenginecontextmenurequest_p.h>
class tst_publicapi : public QObject {
Q_OBJECT
@@ -65,6 +67,12 @@ static QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *>()
<< &QQuickWebEngineSettings::staticMetaObject
<< &QQuickWebEngineFullScreenRequest::staticMetaObject
<< &QQuickWebEngineSingleton::staticMetaObject
+ << &QQuickWebEngineAuthenticationDialogRequest::staticMetaObject
+ << &QQuickWebEngineJavaScriptDialogRequest::staticMetaObject
+ << &QQuickWebEngineColorDialogRequest::staticMetaObject
+ << &QQuickWebEngineFileDialogRequest::staticMetaObject
+ << &QQuickWebEngineFormValidationMessageRequest::staticMetaObject
+ << &QQuickWebEngineContextMenuRequest::staticMetaObject
;
static QList<const char *> knownEnumNames = QList<const char *>();
@@ -351,6 +359,9 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId,PrintedPageOrientation) --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId) --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue) --> void"
+ << "QQuickWebEngineView.canViewSource --> bool"
+ << "QQuickWebEngineView.replaceMisspelledWord(QString) --> void"
+ << "QQuickWebEngineView.viewSource() --> void"
<< "QQuickWebEngineCertificateError.SslPinnedKeyNotInCertificateChain --> Error"
<< "QQuickWebEngineCertificateError.CertificateCommonNameInvalid --> Error"
<< "QQuickWebEngineCertificateError.CertificateDateInvalid --> Error"
@@ -396,6 +407,12 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineDownloadItem.MimeHtmlSaveFormat --> SavePageFormat"
<< "QQuickWebEngineDownloadItem.savePageFormat --> SavePageFormat"
<< "QQuickWebEngineDownloadItem.savePageFormatChanged() --> void"
+ << "QQuickWebEngineDownloadItem.Attachment --> DownloadType"
+ << "QQuickWebEngineDownloadItem.DownloadAttribute --> DownloadType"
+ << "QQuickWebEngineDownloadItem.UserRequested --> DownloadType"
+ << "QQuickWebEngineDownloadItem.SavePage --> DownloadType"
+ << "QQuickWebEngineDownloadItem.type --> DownloadType"
+ << "QQuickWebEngineDownloadItem.typeChanged() --> void"
<< "QQuickWebEngineHistory.items --> QQuickWebEngineHistoryListModel*"
<< "QQuickWebEngineHistory.backItems --> QQuickWebEngineHistoryListModel*"
<< "QQuickWebEngineHistory.forwardItems --> QQuickWebEngineHistoryListModel*"
@@ -438,6 +455,11 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadItem*) --> void"
<< "QQuickWebEngineProfile.downloadFinished(QQuickWebEngineDownloadItem*) --> void"
<< "QQuickWebEngineProfile.NoCache --> HttpCacheType"
+ << "QQuickWebEngineProfile.spellCheckLanguage --> QString"
+ << "QQuickWebEngineProfile.spellCheckEnabled --> bool"
+ << "QQuickWebEngineProfile.spellCheckLanguageChanged() --> void"
+ << "QQuickWebEngineProfile.spellCheckEnabledChanged() --> void"
+ << "QQuickWebEngineProfile.clearHttpCache() --> void"
<< "QQuickWebEngineScript.Deferred --> InjectionPoint"
<< "QQuickWebEngineScript.DocumentReady --> InjectionPoint"
<< "QQuickWebEngineScript.DocumentCreation --> InjectionPoint"
@@ -501,6 +523,8 @@ static QStringList expectedAPI = QStringList()
<< "QQuickWebEngineSettings.accelerated2dCanvasEnabledChanged() --> void"
<< "QQuickWebEngineSettings.autoLoadIconsForPageChanged() --> void"
<< "QQuickWebEngineSettings.touchIconsEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.focusOnNavigationEnabled --> bool"
+ << "QQuickWebEngineSettings.focusOnNavigationEnabledChanged() --> void"
<< "QQuickWebEngineFullScreenRequest.origin --> QUrl"
<< "QQuickWebEngineFullScreenRequest.toggleOn --> bool"
<< "QQuickWebEngineFullScreenRequest.accept() --> void"
diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST
index 035e49a83..a720155d0 100644
--- a/tests/auto/quick/qmltests/BLACKLIST
+++ b/tests/auto/quick/qmltests/BLACKLIST
@@ -6,3 +6,6 @@ osx
[WebViewGeopermission::test_geoPermissionRequest]
osx
+
+[WebEngineViewFocusOnNavigation::test_focusOnNavigation]
+*
diff --git a/tests/auto/quick/qmltests/data/forms.html b/tests/auto/quick/qmltests/data/forms.html
index 8dc3472f2..18133eca6 100644
--- a/tests/auto/quick/qmltests/data/forms.html
+++ b/tests/auto/quick/qmltests/data/forms.html
@@ -19,10 +19,6 @@
<input type="url" value="invalid" required/>
<input type="submit" name="url_invalid"/>
</form>
- <form>
- <input type="url" value="invalid" title="url_title" required/>
- <input type="submit" name="url_title"/>
- </form>
<form>
<input type="email" required/>
@@ -33,8 +29,12 @@
<input type="submit" name="email_invalid"/>
</form>
<form>
- <input type="email" value="invalid" title="email_title" required/>
- <input type="submit" name="email_title"/>
+ <input type="text" title="empty input" required/>
+ <input type="submit" name="input_empty"/>
+ </form>
+ <form>
+ <input type="text" pattern="Lorem ipsum" value="Lorem Ipsum" title="Should type 'Lorem ipsum'"/>
+ <input type="submit" name="lorem_ipsum"/>
</form>
</body>
</html>
diff --git a/tests/auto/quick/qmltests/data/script-with-metadata.js b/tests/auto/quick/qmltests/data/script-with-metadata.js
new file mode 100644
index 000000000..4dcf50f55
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/script-with-metadata.js
@@ -0,0 +1,10 @@
+// ==UserScript==
+// @name Test script
+// @homepageURL http://www.qt.io/
+// @description Test script with metadata block
+// @include *test*.html
+// @exclude *test2.html
+// @run-at document-end
+// ==/UserScript==
+
+document.title = "New title";
diff --git a/tests/auto/quick/qmltests/data/tst_download.qml b/tests/auto/quick/qmltests/data/tst_download.qml
index 7d1e24b4d..e4e93b993 100644
--- a/tests/auto/quick/qmltests/data/tst_download.qml
+++ b/tests/auto/quick/qmltests/data/tst_download.qml
@@ -114,7 +114,7 @@ TestWebEngineView {
compare(downloadState[1], WebEngineDownloadItem.DownloadInProgress)
downloadFinishedSpy.wait()
compare(totalBytes, receivedBytes)
- tryCompare(downloadState, 2, WebEngineDownloadItem.DownloadCompleted)
+ tryCompare(downloadState, "2", WebEngineDownloadItem.DownloadCompleted)
}
function test_downloadCancelled() {
diff --git a/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml
new file mode 100644
index 000000000..ce0fa2e31
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_focusOnNavigation.qml
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtTest 1.0
+import QtWebEngine 1.4
+
+Item {
+ id: container
+ width: 500
+ height: 300
+
+ Row {
+ id: row
+ spacing: 1
+
+ Rectangle {
+ anchors.top: row.top
+ anchors.topMargin: 7
+ width: input.width
+ height: input.height
+ border.color: "black"
+ border.width: 1
+
+ TextInput {
+ id: input
+ width: 80
+ height: 20
+ verticalAlignment: TextInput.AlignVCenter
+ horizontalAlignment: TextInput.AlignHCenter
+ text: "Text"
+ }
+ }
+
+ TestWebEngineView {
+ id: webView
+ width: 300
+ height: 300
+ }
+ }
+
+ TestCase {
+ name: "WebEngineViewFocusOnNavigation"
+ when: windowShown
+ function init() {
+ }
+
+ function test_focusOnNavigation_data() {
+ return [
+ {tag: "focusOnNavigation true", focusOnNavigation: true,
+ viewReceivedFocus: true },
+ {tag: "focusOnNavigation false", focusOnNavigation: false,
+ viewReceivedFocus: false },
+ ]
+ }
+
+ function triggerJavascriptFocus() {
+ var callbackCalled = false;
+ webView.runJavaScript("document.getElementById(\"input\").focus()", function(result) {
+ callbackCalled = true;
+ });
+ wait(100);
+ verify(callbackCalled);
+ }
+
+ function loadAndTriggerFocusAndCompare(data) {
+ verify(webView.waitForLoadSucceeded());
+ triggerJavascriptFocus();
+ compare(webView.activeFocus, data.viewReceivedFocus);
+ }
+
+ function test_focusOnNavigation(data) {
+ // TextInput awlays has initial focus.
+ input.forceActiveFocus();
+
+ // Set focusOnNavigation property to current testing value.
+ webView.settings.focusOnNavigationEnabled = data.focusOnNavigation;
+
+ // Load the content, invoke javascript focus on the view, and check which widget has
+ // focus.
+ webView.loadHtml("<html><head><title>Title</title></head><body>Hello" +
+ "<input id=\"input\" type=\"text\"></body></html>");
+ loadAndTriggerFocusAndCompare(data);
+
+ // Load a different page, and check focus.
+ webView.loadHtml("<html><head><title>Title</title></head><body>Hello 2" +
+ "<input id=\"input\" type=\"text\"></body></html>");
+ loadAndTriggerFocusAndCompare(data);
+
+ // Navigate to previous page in history, check focus.
+ webView.triggerWebAction(WebEngineView.Back)
+ loadAndTriggerFocusAndCompare(data);
+
+ // Navigate to next page in history, check focus.
+ webView.triggerWebAction(WebEngineView.Forward)
+ loadAndTriggerFocusAndCompare(data);
+
+ // Reload page, check focus.
+ webView.triggerWebAction(WebEngineView.Reload)
+ loadAndTriggerFocusAndCompare(data);
+
+ // Reload page bypassing cache, check focus.
+ webView.triggerWebAction(WebEngineView.ReloadAndBypassCache)
+ loadAndTriggerFocusAndCompare(data);
+
+ // Manually forcing focus on web view should work.
+ webView.forceActiveFocus()
+ compare(webView.activeFocus, true)
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/data/tst_formValidation.qml b/tests/auto/quick/qmltests/data/tst_formValidation.qml
index 6da8af7ff..cae41821c 100644
--- a/tests/auto/quick/qmltests/data/tst_formValidation.qml
+++ b/tests/auto/quick/qmltests/data/tst_formValidation.qml
@@ -71,15 +71,6 @@ TestWebEngineView {
keyPress(Qt.Key_Enter)
showSpy.wait()
compare(showSpy.signalArguments[1][0], "Please enter a URL.")
-
- webEngineView.url = Qt.resolvedUrl("about:blank")
- verify(webEngineView.waitForLoadSucceeded())
-
- webEngineView.url = Qt.resolvedUrl("forms.html#url_title")
- verify(webEngineView.waitForLoadSucceeded())
- keyPress(Qt.Key_Enter)
- showSpy.wait()
- compare(showSpy.signalArguments[2][1], "url_title")
}
function test_emailForm() {
@@ -97,15 +88,26 @@ TestWebEngineView {
keyPress(Qt.Key_Enter)
showSpy.wait()
compare(showSpy.signalArguments[1][0], "Please include an '@' in the email address. 'invalid' is missing an '@'.")
+ }
+
+ function test_textForm() {
+ webEngineView.url = Qt.resolvedUrl("forms.html#input_empty")
+ verify(webEngineView.waitForLoadSucceeded())
+ keyPress(Qt.Key_Enter)
+ showSpy.wait()
+ compare(showSpy.signalArguments[0][0], "Please fill out this field.")
+ // Title should be shown for pattern mismatch only
+ compare(showSpy.signalArguments[0][1], "")
webEngineView.url = Qt.resolvedUrl("about:blank")
verify(webEngineView.waitForLoadSucceeded())
- webEngineView.url = Qt.resolvedUrl("forms.html#email_title")
+ webEngineView.url = Qt.resolvedUrl("forms.html#lorem_ipsum")
verify(webEngineView.waitForLoadSucceeded())
keyPress(Qt.Key_Enter)
showSpy.wait()
- compare(showSpy.signalArguments[2][1], "email_title")
+ compare(showSpy.signalArguments[1][0], "Please match the requested format.")
+ compare(showSpy.signalArguments[1][1], "Should type 'Lorem ipsum'")
}
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
index 86fb9281c..ae60e5f5e 100644
--- a/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
+++ b/tests/auto/quick/qmltests/data/tst_keyboardModifierMapping.qml
@@ -53,7 +53,6 @@ TestWebEngineView {
}
function test_keyboardModifierMapping() {
- skip("runJavaScript bug: QTBUG-51746")
webEngineView.url = Qt.resolvedUrl("keyboardModifierMapping.html")
waitForLoadSucceeded();
titleSpy.wait()
diff --git a/tests/auto/quick/qmltests/data/tst_runJavaScript.qml b/tests/auto/quick/qmltests/data/tst_runJavaScript.qml
index 2011d2a5c..beeebc049 100644
--- a/tests/auto/quick/qmltests/data/tst_runJavaScript.qml
+++ b/tests/auto/quick/qmltests/data/tst_runJavaScript.qml
@@ -44,7 +44,6 @@ TestWebEngineView {
TestCase {
name: "WebEngineViewRunJavaScript"
function test_runJavaScript() {
- skip("runJavaScript bug: QTBUG-51746")
var testTitle = "Title to test runJavaScript";
runJavaScript("document.title = \"" + testTitle +"\"");
_waitFor(function() { spy.count > 0; });
diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml
index 358e8f56d..92ae71f0b 100644
--- a/tests/auto/quick/qmltests/data/tst_userScripts.qml
+++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml
@@ -49,6 +49,11 @@ Item {
injectionPoint: WebEngineScript.DocumentReady
}
+ WebEngineScript {
+ id: scriptWithMetadata
+ sourceUrl: Qt.resolvedUrl("script-with-metadata.js")
+ }
+
TestWebEngineView {
id: webEngineView
width: 400
@@ -151,5 +156,22 @@ Item {
webEngineView.waitForLoadSucceeded();
compare(webEngineView.title, "Big user script changed title");
}
+
+ function test_parseMetadataHeader() {
+ compare(scriptWithMetadata.name, "Test script");
+ compare(scriptWithMetadata.injectionPoint, WebEngineScript.DocumentReady);
+
+ webEngineView.userScripts = [ scriptWithMetadata ];
+
+ // @include *test*.html
+ webEngineView.url = Qt.resolvedUrl("test1.html");
+ webEngineView.waitForLoadSucceeded();
+ compare(webEngineView.title, "New title");
+
+ // @exclude *test2.html
+ webEngineView.url = Qt.resolvedUrl("test2.html");
+ webEngineView.waitForLoadSucceeded();
+ compare(webEngineView.title, "Test page with huge link area");
+ }
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_viewSource.qml b/tests/auto/quick/qmltests/data/tst_viewSource.qml
new file mode 100644
index 000000000..746bfcfb3
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_viewSource.qml
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+import QtWebEngine 1.4
+
+TestWebEngineView {
+ id: webEngineView
+ width: 200
+ height: 400
+
+ property var viewRequest: null
+
+ SignalSpy {
+ id: newViewRequestedSpy
+ target: webEngineView
+ signalName: "newViewRequested"
+ }
+
+ SignalSpy {
+ id: titleChangedSpy
+ target: webEngineView
+ signalName: "titleChanged"
+ }
+
+ onNewViewRequested: {
+ viewRequest = {
+ "destination": request.destination,
+ "userInitiated": request.userInitiated
+ };
+
+ request.openIn(webEngineView);
+ }
+
+ TestCase {
+ id: test
+ name: "WebEngineViewSource"
+
+ function init() {
+ webEngineView.url = Qt.resolvedUrl("about:blank");
+ verify(webEngineView.waitForLoadSucceeded());
+
+ newViewRequestedSpy.clear();
+ titleChangedSpy.clear();
+ viewRequest = null;
+ }
+
+ function test_viewSource() {
+ webEngineView.url = Qt.resolvedUrl("test1.html");
+ verify(webEngineView.waitForLoadSucceeded());
+ compare(webEngineView.title, "Test page 1");
+ verify(webEngineView.canViewSource, true);
+
+ titleChangedSpy.clear();
+ webEngineView.viewSource();
+ tryCompare(newViewRequestedSpy, "count", 1);
+ verify(webEngineView.waitForLoadSucceeded());
+ // The first titleChanged signal is emitted by adoptWebContents()
+ tryCompare(titleChangedSpy, "count", 2);
+
+ compare(viewRequest.destination, WebEngineView.NewViewInTab);
+ verify(viewRequest.userInitiated);
+ verify(!webEngineView.canViewSource);
+
+ compare(webEngineView.title, "test1.html");
+ compare(webEngineView.url, "view-source:" + Qt.resolvedUrl("test1.html"));
+ }
+
+ function test_viewSourceURL_data() {
+ var testLocalUrl = "view-source:" + Qt.resolvedUrl("test1.html");
+ var testLocalUrlWithoutScheme = "view-source:" + Qt.resolvedUrl("test1.html").substring(7);
+
+ return [
+ { tag: "view-source:", userInputUrl: "view-source:", loadSucceed: true, url: "view-source:", title: "view-source:" },
+ { tag: "view-source:about:blank", userInputUrl: "view-source:about:blank", loadSucceed: true, url: "view-source:about:blank", title: "view-source:about:blank" },
+ { tag: testLocalUrl, userInputUrl: testLocalUrl, loadSucceed: true, url: testLocalUrl, title: "test1.html" },
+ { tag: testLocalUrlWithoutScheme, userInputUrl: testLocalUrlWithoutScheme, loadSucceed: true, url: testLocalUrl, title: "test1.html" },
+ { tag: "view-source:http://non.existent", userInputUrl: "view-source:http://non.existent", loadSucceed: false, url: "view-source:http://non.existent/", title: "http://non.existent/ is not available" },
+ { tag: "view-source:non.existent", userInputUrl: "view-source:non.existent", loadSucceed: false, url: "view-source:http://non.existent/", title: "http://non.existent/ is not available" },
+ ];
+ }
+
+ function test_viewSourceURL(row) {
+ WebEngine.settings.errorPageEnabled = true
+ webEngineView.url = row.userInputUrl;
+
+ if (row.loadSucceed) {
+ verify(webEngineView.waitForLoadSucceeded());
+ tryCompare(titleChangedSpy, "count", 1);
+ } else {
+ verify(webEngineView.waitForLoadFailed());
+ tryCompare(titleChangedSpy, "count", 2);
+ }
+
+ compare(webEngineView.url, row.url);
+ compare(webEngineView.title, row.title);
+ verify(!webEngineView.canViewSource);
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index 0158a7268..30c3aab30 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -45,6 +45,7 @@ OTHER_FILES += \
$$PWD/data/tst_favicon.qml \
$$PWD/data/tst_faviconDownload.qml \
$$PWD/data/tst_filePicker.qml \
+ $$PWD/data/tst_focusOnNavigation.qml \
$$PWD/data/tst_formValidation.qml \
$$PWD/data/tst_geopermission.qml \
$$PWD/data/tst_javaScriptDialogs.qml \
@@ -63,6 +64,7 @@ OTHER_FILES += \
$$PWD/data/tst_titleChanged.qml \
$$PWD/data/tst_unhandledKeyEventPropagation.qml \
$$PWD/data/tst_userScripts.qml \
+ $$PWD/data/tst_viewSource.qml \
$$PWD/data/tst_webchannel.qml \
$$PWD/data/tst_settings.qml \
$$PWD/data/tst_keyboardModifierMapping.qml \
diff --git a/tests/auto/quick/qquickwebengineview/BLACKLIST b/tests/auto/quick/qquickwebengineview/BLACKLIST
index d4d5c9844..2cde59454 100644
--- a/tests/auto/quick/qquickwebengineview/BLACKLIST
+++ b/tests/auto/quick/qquickwebengineview/BLACKLIST
@@ -1,2 +1,5 @@
[transparentWebEngineViews]
windows
+
+[inputEventForwardingDisabledWhenActiveFocusOnPressDisabled]
+*
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index 078e70255..904dfac26 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -76,6 +76,8 @@ private Q_SLOTS:
void stopSettingFocusWhenDisabled_data();
void inputEventForwardingDisabledWhenActiveFocusOnPressDisabled();
+ void changeLocale();
+
private:
inline QQuickWebEngineView *newWebEngineView();
inline QQuickWebEngineView *webEngineView() const;
@@ -669,5 +671,40 @@ void tst_QQuickWebEngineView::inputEventForwardingDisabledWhenActiveFocusOnPress
QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), true, 1000);
}
+void tst_QQuickWebEngineView::changeLocale()
+{
+ QUrl url("http://non.existent/");
+
+ QLocale::setDefault(QLocale("de"));
+ QQuickWebEngineView *viewDE = newWebEngineView();
+ QSignalSpy titleSpyHU(viewDE, SIGNAL(titleChanged()));
+
+ viewDE->setUrl(url);
+ QVERIFY(waitForLoadFailed(viewDE));
+ QTRY_COMPARE(titleSpyHU.size(), 2);
+ QCOMPARE(viewDE->title(), QStringLiteral("Nicht verf\u00FCgbar: %1").arg(url.toString()));
+
+ QLocale::setDefault(QLocale("en"));
+ QQuickWebEngineView *viewEN = newWebEngineView();
+ QSignalSpy titleSpyEN(viewEN, SIGNAL(titleChanged()));
+
+ viewEN->setUrl(url);
+ QVERIFY(waitForLoadFailed(viewEN));
+ QTRY_COMPARE(titleSpyEN.size(), 2);
+ QCOMPARE(viewEN->title(), QStringLiteral("%1 is not available").arg(url.toString()));
+
+ viewDE->setUrl(QUrl("about:blank"));
+ QVERIFY(waitForLoadSucceeded(viewDE));
+ titleSpyHU.clear();
+
+ viewDE->setUrl(url);
+ QVERIFY(waitForLoadFailed(viewDE));
+ QTRY_COMPARE(titleSpyHU.size(), 2);
+ QCOMPARE(viewDE->title(), QStringLiteral("Nicht verf\u00FCgbar: %1").arg(url.toString()));
+
+ delete viewDE;
+ delete viewEN;
+}
+
QTEST_MAIN(tst_QQuickWebEngineView)
#include "tst_qquickwebengineview.moc"
diff --git a/tests/auto/widgets/qwebenginepage/BLACKLIST b/tests/auto/widgets/qwebenginepage/BLACKLIST
index 2b9453b0e..b1e09777c 100644
--- a/tests/auto/widgets/qwebenginepage/BLACKLIST
+++ b/tests/auto/widgets/qwebenginepage/BLACKLIST
@@ -1,5 +1,8 @@
[comboBoxPopupPositionAfterMove]
-linux
+*
+
+[comboBoxPopupPositionAfterChildMove]
+*
[macCopyUnicodeToClipboard]
osx
diff --git a/tests/auto/widgets/qwebenginepage/resources/test1.html b/tests/auto/widgets/qwebenginepage/resources/test1.html
index b323f966e..5c09f06ed 100644
--- a/tests/auto/widgets/qwebenginepage/resources/test1.html
+++ b/tests/auto/widgets/qwebenginepage/resources/test1.html
@@ -1 +1,6 @@
-<html><body><p>Some text 1</p></body></html>
+<html>
+<head><title>Test page 1</title></head>
+<body>
+Hello.
+</body>
+</html>
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index a8730ce0d..88b7596d9 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -43,6 +43,7 @@
#include <qnetworkreply.h>
#include <qnetworkrequest.h>
#include <qpa/qplatforminputcontext.h>
+#include <qwebenginedownloaditem.h>
#include <qwebenginefullscreenrequest.h>
#include <qwebenginehistory.h>
#include <qwebenginepage.h>
@@ -156,13 +157,13 @@ private Q_SLOTS:
void inputMethods();
void inputMethodsTextFormat_data();
void inputMethodsTextFormat();
- void defaultTextEncoding();
void errorPageExtension();
void errorPageExtensionLoadFinished();
void userAgentNewlineStripping();
void undoActionHaveCustomText();
void renderWidgetHostViewNotShowTopLevel();
void getUserMediaRequest();
+ void savePage();
void crashTests_LazyInitializationOfMainFrame();
@@ -183,7 +184,6 @@ private Q_SLOTS:
// [Qt] tst_QWebEnginePage::infiniteLoopJS() timeouts with DFG JIT
// https://bugs.webkit.org/show_bug.cgi?id=79040
// void infiniteLoopJS();
- void navigatorCookieEnabled();
void deleteQWebEngineViewTwice();
void renderOnRepaintRequestedShouldNotRecurse();
void loadSignalsOrder_data();
@@ -242,6 +242,9 @@ private Q_SLOTS:
void mouseButtonTranslation();
void printToPdf();
+ void viewSource();
+ void viewSourceURL_data();
+ void viewSourceURL();
private:
static QPoint elementCenter(QWebEnginePage *page, const QString &id);
@@ -416,7 +419,7 @@ void tst_QWebEnginePage::geolocationRequestJS()
newPage, SLOT(requestPermission(const QUrl&, QWebEnginePage::Feature)));
QSignalSpy spyLoadFinished(newPage, SIGNAL(loadFinished(bool)));
- newPage->setHtml(QString("<html><body>test</body></html>"), QUrl());
+ newPage->setHtml(QString("<html><body>test</body></html>"), QUrl("qrc://secure/origin"));
QTRY_COMPARE(spyLoadFinished.count(), 1);
if (evaluateJavaScriptSync(newPage, QLatin1String("!navigator.geolocation")).toBool()) {
delete view;
@@ -557,10 +560,15 @@ public:
virtual QWebEnginePage* createWindow(WebWindowType) {
TestPage* page = new TestPage(this);
createdWindows.append(page);
+ emit windowCreated();
return page;
}
QRect requestedGeometry;
+
+signals:
+ void windowCreated();
+
private Q_SLOTS:
void slotGeometryChangeRequested(const QRect& geom) {
requestedGeometry = geom;
@@ -606,20 +614,26 @@ void tst_QWebEnginePage::acceptNavigationRequestNavigationType()
void tst_QWebEnginePage::popupFormSubmission()
{
TestPage page;
+ QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+ QSignalSpy windowCreatedSpy(&page, SIGNAL(windowCreated()));
+
page.settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true);
- page.setHtml("<form name=form1 method=get action='' target=myNewWin>"\
- "<input type=hidden name=foo value='bar'>"\
- "</form>");
- page.runJavaScript("window.open('', 'myNewWin', 'width=500,height=300,toolbar=0')");
+ page.setHtml("<form name='form1' method=get action='' target='myNewWin'>"
+ " <input type='hidden' name='foo' value='bar'>"
+ "</form>");
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+
+ page.runJavaScript("window.open('', 'myNewWin', 'width=500,height=300,toolbar=0');");
evaluateJavaScriptSync(&page, "document.form1.submit();");
+ QTRY_COMPARE(windowCreatedSpy.count(), 1);
- QTest::qWait(500);
// The number of popup created should be one.
QVERIFY(page.createdWindows.size() == 1);
- QString url = page.createdWindows.takeFirst()->url().toString();
+ QTRY_VERIFY(!page.createdWindows[0]->url().isEmpty());
+ QString url = page.createdWindows[0]->url().toString();
+
// Check if the form submission was OK.
- QEXPECT_FAIL("", "https://bugs.webkit.org/show_bug.cgi?id=118597", Continue);
QVERIFY(url.contains("?foo=bar"));
}
@@ -2614,30 +2628,6 @@ void tst_QWebEnginePage::testEnablePersistentStorage()
#endif
}
-void tst_QWebEnginePage::defaultTextEncoding()
-{
- QString defaultCharset = evaluateJavaScriptSync(m_page, "document.defaultCharset").toString();
- QVERIFY(!defaultCharset.isEmpty());
- QCOMPARE(QWebEngineSettings::globalSettings()->defaultTextEncoding(), defaultCharset);
-
- m_page->settings()->setDefaultTextEncoding(QString("utf-8"));
- QCoreApplication::processEvents();
- QString charset = evaluateJavaScriptSync(m_page, "document.defaultCharset").toString();
- QCOMPARE(charset, QString("utf-8"));
- QCOMPARE(m_page->settings()->defaultTextEncoding(), charset);
-
- m_page->settings()->setDefaultTextEncoding(QString());
- QCoreApplication::processEvents();
- charset = evaluateJavaScriptSync(m_page, "document.defaultCharset").toString();
- QVERIFY(!charset.isEmpty());
- QCOMPARE(charset, defaultCharset);
-
- QWebEngineSettings::globalSettings()->setDefaultTextEncoding(QString("utf-8"));
- QCoreApplication::processEvents();
- charset = evaluateJavaScriptSync(m_page, "document.defaultCharset").toString();
- QCOMPARE(charset, QString("utf-8"));
- QCOMPARE(QWebEngineSettings::globalSettings()->defaultTextEncoding(), charset);
-}
#if defined(QWEBENGINEPAGE_ERRORPAGEEXTENSION)
class ErrorPage : public QWebEnginePage
@@ -3067,22 +3057,6 @@ void tst_QWebEnginePage::supportedContentType()
#endif
}
-
-void tst_QWebEnginePage::navigatorCookieEnabled()
-{
-#if !defined(QWEBENGINEPAGE_NETWORKACCESSMANAGER)
- QSKIP("QWEBENGINEPAGE_NETWORKACCESSMANAGER");
-#else
- m_page->networkAccessManager()->setCookieJar(0);
- QVERIFY(!m_page->networkAccessManager()->cookieJar());
- QVERIFY(!evaluateJavaScriptSync(m_page, "navigator.cookieEnabled").toBool());
-
- m_page->networkAccessManager()->setCookieJar(new QNetworkCookieJar());
- QVERIFY(m_page->networkAccessManager()->cookieJar());
- QVERIFY(evaluateJavaScriptSync(m_page, "navigator.cookieEnabled").toBool());
-#endif
-}
-
void tst_QWebEnginePage::thirdPartyCookiePolicy()
{
#if !defined(DUMPRENDERTREESUPPORTQT)
@@ -3497,7 +3471,9 @@ void tst_QWebEnginePage::getUserMediaRequest()
GetUserMediaTestPage *page = new GetUserMediaTestPage();
// We need to load content from a resource in order for the securityOrigin to be valid.
+ QSignalSpy loadSpy(page, SIGNAL(loadFinished(bool)));
page->load(QUrl("qrc:///resources/content.html"));
+ QTRY_COMPARE(loadSpy.count(), 1);
QVERIFY(evaluateJavaScriptSync(page, QStringLiteral("!!navigator.webkitGetUserMedia")).toBool());
evaluateJavaScriptSync(page, QStringLiteral("navigator.webkitGetUserMedia({audio: true}, function() {}, function(){})"));
@@ -3514,9 +3490,45 @@ void tst_QWebEnginePage::getUserMediaRequest()
delete page;
}
+void tst_QWebEnginePage::savePage()
+{
+ QWebEngineView view;
+ QWebEnginePage *page = view.page();
+
+ connect(page->profile(), &QWebEngineProfile::downloadRequested,
+ [] (QWebEngineDownloadItem *item)
+ {
+ connect(item, &QWebEngineDownloadItem::finished,
+ &QTestEventLoop::instance(), &QTestEventLoop::exitLoop, Qt::QueuedConnection);
+ });
+
+ const QString urlPrefix = QStringLiteral("data:text/html,<h1>");
+ const QString text = QStringLiteral("There is Thingumbob shouting!");
+ page->load(QUrl(urlPrefix + text));
+ waitForSignal(page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(toPlainTextSync(page), text);
+
+ // Save the loaded page as HTML.
+ QTemporaryDir tempDir(QDir::tempPath() + "/tst_qwebengineview-XXXXXX");
+ const QString filePath = tempDir.path() + "/thingumbob.html";
+ page->save(filePath, QWebEngineDownloadItem::CompleteHtmlSaveFormat);
+ QTestEventLoop::instance().enterLoop(10);
+
+ // Load something else.
+ page->load(QUrl(urlPrefix + QLatin1String("It's a Snark!")));
+ waitForSignal(page, SIGNAL(loadFinished(bool)));
+ QVERIFY(toPlainTextSync(page) != text);
+
+ // Load the saved page and compare the contents.
+ page->load(QUrl::fromLocalFile(filePath));
+ waitForSignal(page, SIGNAL(loadFinished(bool)));
+ QCOMPARE(toPlainTextSync(page), text);
+}
+
void tst_QWebEnginePage::openWindowDefaultSize()
{
TestPage page;
+ QSignalSpy windowCreatedSpy(&page, SIGNAL(windowCreated()));
QWebEngineView view;
page.setView(&view);
view.show();
@@ -3524,11 +3536,11 @@ void tst_QWebEnginePage::openWindowDefaultSize()
page.settings()->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true);
// Open a default window.
page.runJavaScript("window.open()");
- QTest::qWait(200);
+ QTRY_COMPARE(windowCreatedSpy.count(), 1);
// Open a too small window.
evaluateJavaScriptSync(&page, "window.open('','about:blank','width=10,height=10')");
+ QTRY_COMPARE(windowCreatedSpy.count(), 2);
- QTest::qWait(200);
// The number of popups created should be two.
QCOMPARE(page.createdWindows.size(), 2);
@@ -3770,7 +3782,7 @@ void tst_QWebEnginePage::fullScreenRequested()
if (acceptRequest) request.accept(); else request.reject();
});
- QTest::keyPress(qApp->focusWindow(), Qt::Key_Space);
+ QTest::keyPress(view->focusProxy(), Qt::Key_Space);
QTRY_VERIFY(evaluateJavaScriptSync(page, "document.webkitIsFullScreen").toBool());
page->runJavaScript("document.webkitExitFullscreen()", JavaScriptCallbackUndefined());
QVERIFY(watcher.wait());
@@ -3778,7 +3790,7 @@ void tst_QWebEnginePage::fullScreenRequested()
acceptRequest = false;
page->runJavaScript("document.webkitFullscreenEnabled", JavaScriptCallback(true));
- QTest::keyPress(qApp->focusWindow(), Qt::Key_Space);
+ QTest::keyPress(view->focusProxy(), Qt::Key_Space);
QVERIFY(watcher.wait());
page->runJavaScript("document.webkitIsFullScreen", JavaScriptCallback(false));
QVERIFY(watcher.wait());
@@ -4341,23 +4353,39 @@ void tst_QWebEnginePage::horizontalScrollAfterBack()
#endif
}
+class WebView : public QWebEngineView
+{
+ Q_OBJECT
+signals:
+ void repaintRequested();
+
+protected:
+ bool event(QEvent *event) {
+ if (event->type() == QEvent::UpdateRequest)
+ emit repaintRequested();
+
+ return QWebEngineView::event(event);
+ }
+};
+
void tst_QWebEnginePage::evaluateWillCauseRepaint()
{
-#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT)
- QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT");
-#else
- QWebEngineView view;
- QString html("<html><body>top<div id=\"junk\" style=\"display: block;\">"
- "junk</div>bottom</body></html>");
- view.setHtml(html);
+ WebView view;
view.show();
-
QTest::qWaitForWindowExposed(&view);
- view.page()->evaluateJavaScript(
- "document.getElementById('junk').style.display = 'none';");
- ::waitForSignal(view.page(), SIGNAL(repaintRequested(QRect)));
-#endif
+ QString html("<html><body>"
+ " top"
+ " <div id=\"junk\" style=\"display: block;\">junk</div>"
+ " bottom"
+ "</body></html>");
+
+ QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ view.setHtml(html);
+ QTRY_COMPARE(loadSpy.count(), 1);
+
+ evaluateJavaScriptSync(view.page(), "document.getElementById('junk').style.display = 'none';");
+ ::waitForSignal(&view, SIGNAL(repaintRequested()));
}
void tst_QWebEnginePage::setContent_data()
@@ -5006,5 +5034,73 @@ QPoint tst_QWebEnginePage::elementCenter(QWebEnginePage *page, const QString &id
return QPoint(rectList.at(0).toInt(), rectList.at(1).toInt());
}
+void tst_QWebEnginePage::viewSource()
+{
+ TestPage page;
+ QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+ QSignalSpy windowCreatedSpy(&page, SIGNAL(windowCreated()));
+ const QUrl url("qrc:/resources/test1.html");
+
+ page.load(url);
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+ QCOMPARE(page.title(), QStringLiteral("Test page 1"));
+ QVERIFY(page.canViewSource());
+
+ page.viewSource();
+ QTRY_COMPARE(windowCreatedSpy.count(), 1);
+ QCOMPARE(page.createdWindows.size(), 1);
+
+ QTRY_COMPARE(page.createdWindows[0]->url().toString(), QStringLiteral("view-source:%1").arg(url.toString()));
+ QTRY_COMPARE(page.createdWindows[0]->title(), QStringLiteral("view-source:%1").arg(url.toString()));
+ QVERIFY(!page.createdWindows[0]->canViewSource());
+}
+
+void tst_QWebEnginePage::viewSourceURL_data()
+{
+ QTest::addColumn<QUrl>("userInputUrl");
+ QTest::addColumn<bool>("loadSucceed");
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<QString>("title");
+
+ QTest::newRow("view-source:") << QUrl("view-source:") << true << QUrl("view-source:") << QString("view-source:");
+ QTest::newRow("view-source:about:blank") << QUrl("view-source:about:blank") << true << QUrl("view-source:about:blank") << QString("view-source:about:blank");
+
+ QUrl testLocalUrl = QUrl(QString("view-source:%1").arg(QUrl::fromLocalFile(TESTS_SOURCE_DIR + QLatin1String("qwebenginepage/resources/test1.html")).toString()));
+ QUrl testLocalUrlWithoutScheme = QUrl(QString("view-source:%1").arg(TESTS_SOURCE_DIR + QLatin1String("qwebenginepage/resources/test1.html")));
+ QTest::newRow(testLocalUrl.toString().toStdString().c_str()) << testLocalUrl << true << testLocalUrl << QString("test1.html");
+ QTest::newRow(testLocalUrlWithoutScheme.toString().toStdString().c_str()) << testLocalUrlWithoutScheme << true << testLocalUrl << QString("test1.html");
+
+ QUrl testResourceUrl = QUrl("view-source:qrc:/resources/test1.html");
+ QTest::newRow(testResourceUrl.toString().toStdString().c_str()) << testResourceUrl << true << testResourceUrl << testResourceUrl.toString();
+
+ QTest::newRow("view-source:http://non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QString("http://non.existent/ is not available");
+ QTest::newRow("view-source:non.existent") << QUrl("view-source:non.existent") << false << QUrl("view-source:http://non.existent/") << QString("http://non.existent/ is not available");
+}
+
+void tst_QWebEnginePage::viewSourceURL()
+{
+ 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);
+
+ QFETCH(QUrl, userInputUrl);
+ QFETCH(bool, loadSucceed);
+ QFETCH(QUrl, url);
+ QFETCH(QString, title);
+
+ QWebEnginePage *page = new QWebEnginePage;
+ QSignalSpy loadFinishedSpy(page, SIGNAL(loadFinished(bool)));
+
+ page->load(userInputUrl);
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+ QList<QVariant> arguments = loadFinishedSpy.takeFirst();
+
+ QCOMPARE(arguments.at(0).toBool(), loadSucceed);
+ QCOMPARE(page->url(), url);
+ QCOMPARE(page->title(), title);
+ QVERIFY(!page->canViewSource());
+
+ delete page;
+}
+
QTEST_MAIN(tst_QWebEnginePage)
#include "tst_qwebenginepage.moc"
diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
index 579a0f776..093bc2e43 100644
--- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
+++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
@@ -52,6 +52,7 @@ private Q_SLOTS:
void customUserAgent();
void httpAcceptLanguage();
void downloadItem();
+ void changePersistentPath();
};
void tst_QWebEngineProfile::defaultProfile()
@@ -375,5 +376,24 @@ void tst_QWebEngineProfile::downloadItem()
QTRY_COMPARE(downloadSpy.count(), 1);
}
+void tst_QWebEngineProfile::changePersistentPath()
+{
+ QWebEngineProfile testProfile(QStringLiteral("Test"));
+ const QString oldPath = testProfile.persistentStoragePath();
+ QVERIFY(oldPath.endsWith(QStringLiteral("Test")));
+
+ // Make sure the profile has been used and the url-request-context-getter instantiated:
+ QWebEnginePage page(&testProfile);
+ QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+ page.load(QUrl("http://qt-project.org"));
+ if (!loadFinishedSpy.wait(10000) || !loadFinishedSpy.at(0).at(0).toBool())
+ QSKIP("Couldn't load page from network, skipping test.");
+
+ // Test we do not crash (QTBUG-55322):
+ testProfile.setPersistentStoragePath(oldPath + QLatin1Char('2'));
+ const QString newPath = testProfile.persistentStoragePath();
+ QVERIFY(newPath.endsWith(QStringLiteral("Test2")));
+}
+
QTEST_MAIN(tst_QWebEngineProfile)
#include "tst_qwebengineprofile.moc"
diff --git a/tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp b/tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp
index 0f6a6062e..d8c18e509 100644
--- a/tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp
+++ b/tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp
@@ -27,6 +27,8 @@ class tst_QWebEngineSettings: public QObject {
private Q_SLOTS:
void resetAttributes();
+ void defaultFontFamily_data();
+ void defaultFontFamily();
};
void tst_QWebEngineSettings::resetAttributes()
@@ -58,6 +60,27 @@ void tst_QWebEngineSettings::resetAttributes()
QCOMPARE(defaultSize, settings->fontSize(QWebEngineSettings::MinimumFontSize));
}
+void tst_QWebEngineSettings::defaultFontFamily_data()
+{
+ QTest::addColumn<int>("fontFamily");
+
+ QTest::newRow("StandardFont") << static_cast<int>(QWebEngineSettings::StandardFont);
+ QTest::newRow("FixedFont") << static_cast<int>(QWebEngineSettings::FixedFont);
+ QTest::newRow("SerifFont") << static_cast<int>(QWebEngineSettings::SerifFont);
+ QTest::newRow("SansSerifFont") << static_cast<int>(QWebEngineSettings::SansSerifFont);
+ QTest::newRow("CursiveFont") << static_cast<int>(QWebEngineSettings::CursiveFont);
+ QTest::newRow("FantasyFont") << static_cast<int>(QWebEngineSettings::FantasyFont);
+}
+
+void tst_QWebEngineSettings::defaultFontFamily()
+{
+ QWebEngineProfile profile;
+ QWebEngineSettings *settings = profile.settings();
+
+ QFETCH(int, fontFamily);
+ QVERIFY(!settings->fontFamily(static_cast<QWebEngineSettings::FontFamily>(fontFamily)).isEmpty());
+}
+
QTEST_MAIN(tst_QWebEngineSettings)
#include "tst_qwebenginesettings.moc"
diff --git a/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp
index 2dfe3305d..534d40f45 100644
--- a/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp
+++ b/tests/auto/widgets/qwebenginespellcheck/tst_qwebenginespellcheck.cpp
@@ -37,12 +37,13 @@ class WebView : public QWebEngineView
{
Q_OBJECT
public:
- void activateMenu(const QPoint &position)
+ void activateMenu(QWidget *widget, const QPoint &position)
{
- QTest::mouseMove(focusWidget(), position);
- QTest::mousePress(focusWidget(), Qt::RightButton, 0, position);
+ QTest::mouseMove(widget, position);
+ QTest::mousePress(widget, Qt::RightButton, 0, position);
QContextMenuEvent evcont(QContextMenuEvent::Mouse, position, mapToGlobal(position));
event(&evcont);
+ QTest::mouseRelease(widget, Qt::RightButton, 0, position);
}
const QWebEngineContextMenuData& data()
@@ -142,6 +143,7 @@ void tst_QWebEngineSpellcheck::spellcheck()
//type text, spellchecker needs time
QTest::mouseMove(m_view->focusWidget(), QPoint(20,20));
QTest::mousePress(m_view->focusWidget(), Qt::LeftButton, 0, QPoint(20,20));
+ QTest::mouseRelease(m_view->focusWidget(), Qt::LeftButton, 0, QPoint(20,20));
QString text("I lovee Qt ....");
for (int i = 0; i < text.length(); i++) {
QTest::keyClicks(m_view->focusWidget(), text.at(i));
@@ -153,7 +155,7 @@ void tst_QWebEngineSpellcheck::spellcheck()
QVERIFY(result == text);
// open menu on misspelled word
- m_view->activateMenu(rect.center());
+ m_view->activateMenu(m_view->focusWidget(), rect.center());
waitForSignal(m_view, SIGNAL(menuReady()));
// check if menu is valid
@@ -170,8 +172,7 @@ void tst_QWebEngineSpellcheck::spellcheck()
// check replace word
m_view->page()->replaceMisspelledWord("love");
text = "I love Qt ....";
- result = evaluateJavaScriptSync(m_view->page(), "text();").toString();
- QVERIFY(result == text);
+ QTRY_VERIFY(evaluateJavaScriptSync(m_view->page(), "text();").toString() == text);
}
QTEST_MAIN(tst_QWebEngineSpellcheck)
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index afb53ba20..ac142bb38 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -31,6 +31,8 @@
#include <qdiriterator.h>
#include <qstackedlayout.h>
#include <qtemporarydir.h>
+#include <QLineEdit>
+#include <QHBoxLayout>
#define VERIFY_INPUTMETHOD_HINTS(actual, expect) \
QVERIFY(actual == expect);
@@ -74,6 +76,10 @@ private Q_SLOTS:
void doNotSendMouseKeyboardEventsWhenDisabled_data();
void stopSettingFocusWhenDisabled();
void stopSettingFocusWhenDisabled_data();
+ void focusOnNavigation_data();
+ void focusOnNavigation();
+
+ void changeLocale();
};
// This will be called before the first test function is executed.
@@ -357,23 +363,21 @@ void tst_QWebEngineView::unhandledKeyEventPropagation()
evaluateJavaScriptSync(webView.page(), "document.body.firstChild.focus()");
- QTest::sendKeyEvent(QTest::Press, parentWidget.windowHandle(), Qt::Key_A, 'a', Qt::NoModifier);
- QTest::sendKeyEvent(QTest::Release, parentWidget.windowHandle(), Qt::Key_A, 'a', Qt::NoModifier);
- QTest::sendKeyEvent(QTest::Press, parentWidget.windowHandle(), Qt::Key_Left, QString(), Qt::NoModifier);
- QTest::sendKeyEvent(QTest::Release, parentWidget.windowHandle(), Qt::Key_Left, QString(), Qt::NoModifier);
- QTest::sendKeyEvent(QTest::Press, parentWidget.windowHandle(), Qt::Key_Left, QString(), Qt::NoModifier);
- QTest::sendKeyEvent(QTest::Release, parentWidget.windowHandle(), Qt::Key_Left, QString(), Qt::NoModifier);
+ QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_A, 'a', Qt::NoModifier);
+ QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_A, 'a', Qt::NoModifier);
+ QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_Left, QString(), Qt::NoModifier);
+ QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_Left, QString(), Qt::NoModifier);
+ QTest::sendKeyEvent(QTest::Press, webView.focusProxy(), Qt::Key_Left, QString(), Qt::NoModifier);
+ QTest::sendKeyEvent(QTest::Release, webView.focusProxy(), Qt::Key_Left, QString(), Qt::NoModifier);
// All this happens asychronously, wait for the last release event to know when we're done.
- for (int i = 0; i < 20 && parentWidget.releaseEvents.size() < 3; ++i)
- QTest::qWait(100);
+ QTRY_COMPARE(parentWidget.releaseEvents.size(), 3);
// The page will consume the 'a' and the first left key presses, the second left won't be
// used since the cursor will already be at the left end of the text input.
// Key releases will all come back unconsumed.
QCOMPARE(parentWidget.pressEvents.size(), 1);
QCOMPARE(parentWidget.pressEvents[0].key(), (int)Qt::Key_Left);
- QCOMPARE(parentWidget.releaseEvents.size(), 3);
QCOMPARE(parentWidget.releaseEvents[0].key(), (int)Qt::Key_A);
QCOMPARE(parentWidget.releaseEvents[1].key(), (int)Qt::Key_Left);
QCOMPARE(parentWidget.releaseEvents[2].key(), (int)Qt::Key_Left);
@@ -743,5 +747,117 @@ void tst_QWebEngineView::stopSettingFocusWhenDisabled_data()
QTest::newRow("disabled view does not get focus") << false << false;
}
+void tst_QWebEngineView::focusOnNavigation_data()
+{
+ QTest::addColumn<bool>("focusOnNavigation");
+ QTest::addColumn<bool>("viewReceivedFocus");
+ QTest::newRow("focusOnNavigation true") << true << true;
+ QTest::newRow("focusOnNavigation false") << false << false;
+}
+
+void tst_QWebEngineView::focusOnNavigation()
+{
+ QFETCH(bool, focusOnNavigation);
+ QFETCH(bool, viewReceivedFocus);
+
+#define triggerJavascriptFocus()\
+ evaluateJavaScriptSync(webView->page(), "document.getElementById(\"input\").focus()");
+#define loadAndTriggerFocusAndCompare()\
+ QTRY_COMPARE(loadSpy.count(), 1);\
+ triggerJavascriptFocus();\
+ QTRY_COMPARE(webView->hasFocus(), viewReceivedFocus);
+
+ // Create a container widget, that will hold a line edit that has initial focus, and a web
+ // engine view.
+ QScopedPointer<QWidget> containerWidget(new QWidget);
+ QLineEdit *label = new QLineEdit;
+ label->setText(QString::fromLatin1("Text"));
+ label->setFocus();
+
+ // Create the web view, and set its focusOnNavigation property.
+ QWebEngineView *webView = new QWebEngineView;
+ QWebEngineSettings *settings = webView->page()->settings();
+ settings->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, focusOnNavigation);
+ webView->resize(300, 300);
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(label);
+ layout->addWidget(webView);
+
+ containerWidget->setLayout(layout);
+ containerWidget->show();
+ QTest::qWaitForWindowExposed(containerWidget.data());
+
+ // Load the content, invoke javascript focus on the view, and check which widget has focus.
+ QSignalSpy loadSpy(webView, SIGNAL(loadFinished(bool)));
+ webView->setHtml("<html><head><title>Title</title></head><body>Hello"
+ "<input id=\"input\" type=\"text\"></body></html>");
+ loadAndTriggerFocusAndCompare();
+
+ // Load a different page, and check focus.
+ loadSpy.clear();
+ webView->setHtml("<html><head><title>Title</title></head><body>Hello 2"
+ "<input id=\"input\" type=\"text\"></body></html>");
+ loadAndTriggerFocusAndCompare();
+
+ // Navigate to previous page in history, check focus.
+ loadSpy.clear();
+ webView->triggerPageAction(QWebEnginePage::Back);
+ loadAndTriggerFocusAndCompare();
+
+ // Navigate to next page in history, check focus.
+ loadSpy.clear();
+ webView->triggerPageAction(QWebEnginePage::Forward);
+ loadAndTriggerFocusAndCompare();
+
+ // Reload page, check focus.
+ loadSpy.clear();
+ webView->triggerPageAction(QWebEnginePage::Reload);
+ loadAndTriggerFocusAndCompare();
+
+ // Reload page bypassing cache, check focus.
+ loadSpy.clear();
+ webView->triggerPageAction(QWebEnginePage::ReloadAndBypassCache);
+ loadAndTriggerFocusAndCompare();
+
+ // Manually forcing focus on web view should work.
+ webView->setFocus();
+ QTRY_COMPARE(webView->hasFocus(), true);
+
+ // Clean up.
+#undef loadAndTriggerFocusAndCompare
+#undef triggerJavascriptFocus
+}
+
+void tst_QWebEngineView::changeLocale()
+{
+ QUrl url("http://non.existent/");
+
+ QLocale::setDefault(QLocale("de"));
+ QWebEngineView viewDE;
+ viewDE.setUrl(url);
+
+ QVERIFY(waitForSignal(&viewDE, SIGNAL(titleChanged(QString))));
+ QVERIFY(waitForSignal(&viewDE, SIGNAL(loadFinished(bool))));
+ QCOMPARE(viewDE.title(), QStringLiteral("Nicht verf\u00FCgbar: %1").arg(url.toString()));
+
+ QLocale::setDefault(QLocale("en"));
+ QWebEngineView viewEN;
+ viewEN.setUrl(url);
+
+ QVERIFY(waitForSignal(&viewEN, SIGNAL(titleChanged(QString))));
+ QVERIFY(waitForSignal(&viewEN, SIGNAL(loadFinished(bool))));
+ QCOMPARE(viewEN.title(), QStringLiteral("%1 is not available").arg(url.toString()));
+
+ viewDE.setUrl(QUrl("about:blank"));
+ QVERIFY(waitForSignal(&viewDE, SIGNAL(loadFinished(bool))));
+
+ viewDE.setUrl(url);
+
+ QVERIFY(waitForSignal(&viewDE, SIGNAL(titleChanged(QString))));
+ QVERIFY(waitForSignal(&viewDE, SIGNAL(loadFinished(bool))));
+ QCOMPARE(viewDE.title(), QStringLiteral("Nicht verf\u00FCgbar: %1").arg(url.toString()));
+}
+
QTEST_MAIN(tst_QWebEngineView)
#include "tst_qwebengineview.moc"
diff --git a/tests/quicktestbrowser/BrowserWindow.qml b/tests/quicktestbrowser/BrowserWindow.qml
index 4275fd503..2d8807e8c 100644
--- a/tests/quicktestbrowser/BrowserWindow.qml
+++ b/tests/quicktestbrowser/BrowserWindow.qml
@@ -28,7 +28,6 @@
import QtQuick 2.1
import QtWebEngine 1.2
-import QtWebEngine.experimental 1.0
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
@@ -393,10 +392,6 @@ ApplicationWindow {
permBar.requestedFeature = feature;
permBar.visible = true;
}
-
- experimental {
- extraContextMenuEntriesComponent: ContextMenuExtras {}
- }
}
Rectangle {
diff --git a/tests/quicktestbrowser/DownloadView.qml b/tests/quicktestbrowser/DownloadView.qml
index 90d161ce3..eb945eccc 100644
--- a/tests/quicktestbrowser/DownloadView.qml
+++ b/tests/quicktestbrowser/DownloadView.qml
@@ -30,7 +30,6 @@ import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Controls.Styles 1.0
import QtWebEngine 1.0
-import QtWebEngine.experimental 1.0
import QtQuick.Layouts 1.0
Rectangle {
diff --git a/tests/quicktestbrowser/quicktestbrowser.pro b/tests/quicktestbrowser/quicktestbrowser.pro
index 996e82a63..b4fb9a58d 100644
--- a/tests/quicktestbrowser/quicktestbrowser.pro
+++ b/tests/quicktestbrowser/quicktestbrowser.pro
@@ -1,4 +1,4 @@
-requires(contains(QT_CONFIG, accessibility))
+requires(qtConfig(accessibility))
TEMPLATE = app
TARGET = quicktestbrowser
diff --git a/tests/quicktestbrowser/resources.qrc b/tests/quicktestbrowser/resources.qrc
index 2dcda4d0d..b1652852b 100644
--- a/tests/quicktestbrowser/resources.qrc
+++ b/tests/quicktestbrowser/resources.qrc
@@ -3,7 +3,6 @@
<file>ApplicationRoot.qml</file>
<file>BrowserDialog.qml</file>
<file>BrowserWindow.qml</file>
- <file>ContextMenuExtras.qml</file>
<file>FeaturePermissionBar.qml</file>
<file>FullScreenNotification.qml</file>
<file>ButtonWithMenu.qml</file>
diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf
index 6a67bf097..89fa3a242 100644
--- a/tools/qmake/mkspecs/features/configure.prf
+++ b/tools/qmake/mkspecs/features/configure.prf
@@ -21,13 +21,14 @@ defineTest(runConfigure) {
}
linux {
+ QT_FOR_CONFIG += gui-private
!config_khr:skipBuild("khronos development headers appear to be missing (mesa/libegl1-mesa-dev)")
REQUIRED_PACKAGES = dbus-1 fontconfig
- !cross_compile: contains(QT_CONFIG, xcb): REQUIRED_PACKAGES += libdrm xcomposite xcursor xi xrandr xscrnsaver xtst
+ !cross_compile: qtConfig(xcb): REQUIRED_PACKAGES += libdrm xcomposite xcursor xi xrandr xscrnsaver xtst
contains(QT_CONFIG, pulseaudio): REQUIRED_PACKAGES += libpulse
- contains(QT_CONFIG, system-png): REQUIRED_PACKAGES += libpng
- contains(QT_CONFIG, system-harfbuzz): REQUIRED_PACKAGES += harfbuzz
+ qtConfig(system-png): REQUIRED_PACKAGES += libpng
+ qtConfig(system-harfbuzz): REQUIRED_PACKAGES += harfbuzz
!cross_compile: REQUIRED_PACKAGES += libpci
for(package, $$list($$REQUIRED_PACKAGES)) {
@@ -62,9 +63,6 @@ defineTest(runConfigure) {
}
}
- # Spellcheck support is moved to dev
- WEBENGINE_CONFIG += no_spellcheck
-
isEmpty(skipBuildReason): {
cache(CONFIG, add, $$list(webengine_successfully_configured))
!isEmpty(WEBENGINE_CONFIG) {
@@ -72,7 +70,6 @@ defineTest(runConfigure) {
export(WEBENGINE_CONFIG)
}
}
-
}
# This is called from default_post, at which point we've also parsed
diff --git a/tools/qmake/mkspecs/features/functions.prf b/tools/qmake/mkspecs/features/functions.prf
index cd4f4a007..d109e2859 100644
--- a/tools/qmake/mkspecs/features/functions.prf
+++ b/tools/qmake/mkspecs/features/functions.prf
@@ -1,4 +1,20 @@
+defineTest(isQtMinimum) {
+ !equals(QT_MAJOR_VERSION, $$1): return(false)
+ count(ARGS, 1, greaterThan) {
+ lessThan(QT_MINOR_VERSION, $$2): return(false)
+ }
+ return(true)
+}
+
+!isQtMinimum(5, 8) {
+ defineTest(qtConfig) {
+ contains(QT_CONFIG, $$1): return(true)
+ return(false)
+ }
+}
+
defineTest(isPlatformSupported) {
+ QT_FOR_CONFIG += gui-private
linux {
!gcc:!clang {
skipBuild("Qt WebEngine on Linux requires clang or GCC.")
@@ -11,26 +27,30 @@ defineTest(isPlatformSupported) {
return(false)
}
msvc {
- !equals(MSVC_VER, "12.0"):!equals(MSVC_VER, "14.0") {
- skipBuild("Qt WebEngine on Windows requires MSVC 2013 or MSVC 2015.")
+ !equals(MSVC_VER, "14.0") {
+ skipBuild("Qt WebEngine on Windows requires MSVC 2015 Update 2 or later.")
return(false)
}
} else {
- skipBuild("Qt WebEngine on Windows requires MSVC 2013 or MSVC 2015.")
+ skipBuild("Qt WebEngine on Windows requires MSVC 2015 Update 2 or later.")
return(false)
}
isBuildingOnWin32() {
skipBuild("Qt WebEngine on Windows must be built on a 64-bit machine.")
}
+ !isMinWinSDKVersion(10, 10586): {
+ skipBuild("Qt WebEngine on Windows requires a Windows SDK version 10.0.10586 or newer.")
+ return(false)
+ }
} else:osx {
- lessThan(QMAKE_XCODE_VERSION, 6.1) {
- skipBuild("Using XCode version $$QMAKE_XCODE_VERSION, but at least version 6.1 is required to build Qt WebEngine.")
+ lessThan(QMAKE_XCODE_VERSION, 6.3) {
+ skipBuild("Using XCode version $$QMAKE_XCODE_VERSION, but at least version 6.3 is required to build Qt WebEngine.")
return(false)
}
- # We require OS X 10.9 (darwin version 13.0.0) or newer
+ # We require OS X 10.10 (darwin version 14.0.0) or newer
darwin_major_version = $$section(QMAKE_HOST.version, ., 0, 0)
- lessThan(darwin_major_version, 13) {
- skipBuild("Qt WebEngine requires OS X version 10.9 or newer.")
+ lessThan(darwin_major_version, 14) {
+ skipBuild("Qt WebEngine requires OS X version 10.10 or newer.")
return(false)
}
!isMinOSXSDKVersion(10, 10): {
@@ -46,7 +66,7 @@ defineTest(isPlatformSupported) {
skipBuild("C++11 support is required in order to build chromium.")
return(false)
}
- contains(QT_CONFIG, mirclient) {
+ qtConfig(mirclient) {
skipBuild("Mir is not yet supported as graphics backend for Qt WebEngine.")
return(false)
}
@@ -86,7 +106,7 @@ defineTest(isGCCVersionSupported) {
}
defineTest(isQMLTestSupportApiEnabled) {
- contains(QT_CONFIG, private_tests): return(true) # enable for developer-build
+ qtConfig(private_tests): return(true) # enable for developer-build
contains(QT_BUILD_PARTS, tests): return(true)
contains(WEBENGINE_CONFIG, testsupport): return(true)
return(false)
@@ -124,6 +144,22 @@ defineTest(isMinOSXSDKVersion) {
return(false)
}
+defineTest(isMinWinSDKVersion) {
+ requested_major = $$1
+ requested_minor = $$2
+ WIN_SDK_VERSION = $$(WindowsSDKVersion)
+
+ # major.0.minor
+ major_version = $$section(WIN_SDK_VERSION, ., 0, 0)
+ minor_version = $$section(WIN_SDK_VERSION, ., 2, 2)
+
+ greaterThan(major_version, $$requested_major):return(true)
+ equals(major_version, $$requested_major):greaterThan(minor_version, $$requested_minor):return(true)
+ equals(major_version, $$requested_major):equals(minor_version, $$requested_minor)::return(true)
+
+ return(false)
+}
+
# Map to the correct target type for gyp
defineReplace(toGypTargetType) {
equals(TEMPLATE, "app"):return("executable")
diff --git a/tools/qmake/mkspecs/features/gyp_generator.prf b/tools/qmake/mkspecs/features/gyp_generator.prf
index 4cf7cd2f4..2fbd74730 100644
--- a/tools/qmake/mkspecs/features/gyp_generator.prf
+++ b/tools/qmake/mkspecs/features/gyp_generator.prf
@@ -14,6 +14,8 @@ defineReplace(mocAction) {
OUTPUT_NAME = $$mocOutput($$INPUT_FILE)
DEFINES_LIST = $$join(DEFINES, " -D", -D)
INCPATH = $$join(INCLUDEPATH, " -I", -I)
+ # we don't generate a moc_predef file yet.
+ MOC_PREDEF_FILE =
MOC_COMMAND = $$clean_path($$mocCmdBase())
MOC_COMMAND = $$replace(MOC_COMMAND, $$re_escape("$(DEFINES)"), $$DEFINES_LIST)
MOC_COMMAND = $$replace(MOC_COMMAND, $$re_escape("$(INCPATH)"), $$INCPATH)
diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py
index 25b3dc15e..1c65c47ed 100755
--- a/tools/scripts/take_snapshot.py
+++ b/tools/scripts/take_snapshot.py
@@ -92,8 +92,13 @@ def isInChromiumBlacklist(file_path):
not 'media/desktop_media_list.h' in file_path and
not 'media/desktop_streams_registry.' in file_path and
not 'common/chrome_switches.' in file_path and
- not 'common/localized_error.' in file_path and
+ not 'common/content_restriction.h' in file_path and
not 'common/spellcheck_' in file_path and
+ not '/extensions/api/' in file_path and
+ not '/extensions/browser/api/' in file_path and
+ not '/extensions/permissions/' in file_path and
+ not '/renderer_host/pepper/' in file_path and
+ not '/renderer/pepper/' in file_path and
not '/spellchecker/' in file_path and
not '/tools/convert_dict/' in file_path and
not file_path.endswith('cf_resources.rc') and
@@ -105,47 +110,32 @@ def isInChromiumBlacklist(file_path):
or file_path.startswith('chrome_frame')
or file_path.startswith('chromeos')
or file_path.startswith('cloud_print')
- or (file_path.startswith('components') and
- not file_path.startswith('components/cdm') and
- not file_path.startswith('components/device_event_log') and
- not file_path.startswith('components/devtools_') and
- not file_path.startswith('components/error_page') and
- not file_path.startswith('components/keyed_service') and
- not file_path.startswith('components/mime_util') and
- not file_path.startswith('components/precache') and
- not file_path.startswith('components/pref_registry') and
- not file_path.startswith('components/printing') and
- not file_path.startswith('components/resources') and
- not file_path.startswith('components/scheduler') and
- not file_path.startswith('components/security_interstitials') and
- not file_path.startswith('components/startup_metric_utils') and
- not file_path.startswith('components/strings') and
- not file_path.startswith('components/tracing') and
- not file_path.startswith('components/url_formatter') and
- not file_path.startswith('components/user_prefs') and
- not file_path.startswith('components/version_') and
- not file_path.startswith('components/visitedlink') and
- not file_path.startswith('components/web_cache') and
- not file_path.startswith('components/webcrypto') and
- not file_path.startswith('components/webusb') and
- not file_path.endswith('.grd') and
- not file_path.endswith('.grdp') and
- not 'components_strings' in file_path)
+ 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/mus/')
+ 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_driver/')
+ 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'))
+ not file_path.startswith('content/shell/common') and
+ not file_path.endswith('.grd'))
or file_path.startswith('courgette')
- or (file_path.startswith('extensions') and
- not 'browser/extension_function_registry.h' in file_path and
- not 'browser/extension_function_histogram_value.h' in file_path and
- not 'browser/notification_types.cc' in file_path and
- not 'browser/notification_types.h' in 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('net/android/java')
- or file_path.startswith('pdf')
or file_path.startswith('remoting')
or file_path.startswith('rlz')
or file_path.startswith('sync')
@@ -185,7 +175,8 @@ def isInChromiumBlacklist(file_path):
or file_path.startswith('third_party/jsr-305/src')
or file_path.startswith('third_party/junit')
or file_path.startswith('third_party/libphonenumber')
- or file_path.startswith('third_party/libaddressinput')
+ 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')
@@ -195,32 +186,22 @@ def isInChromiumBlacklist(file_path):
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/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/pdfium')
or file_path.startswith('third_party/psyco_win32')
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/trace-viewer')
or file_path.startswith('third_party/undoview')
or file_path.startswith('third_party/webgl')
+ or file_path.startswith('tools/android')
+ or file_path.startswith('tools/luci_go')
+ or file_path.startswith('tools/metrics')
or file_path.startswith('tools/memory_inspector')
- or (file_path.startswith('tools') and
- not file_path.startswith('tools/clang') and
- not file_path.startswith('tools/compile_test') and
- not file_path.startswith('tools/generate_library_loader') and
- not file_path.startswith('tools/generate_shim_headers') and
- not file_path.startswith('tools/generate_stubs') and
- not file_path.startswith('tools/grit') and
- not file_path.startswith('tools/gyp') and
- not file_path.startswith('tools/json_comment_eater') and
- not file_path.startswith('tools/json_schema_compiler') and
- not file_path.startswith('tools/idl_parser') and
- not file_path.startswith('tools/memory') and
- not file_path.startswith('tools/msan') and
- not file_path.startswith('tools/protoc_wrapper') and
- not file_path.startswith('tools/ubsan'))
+ or file_path.startswith('tools/perf')
+ or file_path.startswith('tools/swarming_client')
or file_path.startswith('ui/android/java')
or file_path.startswith('ui/app_list')
or file_path.startswith('ui/base/ime/chromeos')
diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py
index 6029bbdc9..181700d92 100644
--- a/tools/scripts/version_resolver.py
+++ b/tools/scripts/version_resolver.py
@@ -38,9 +38,9 @@ import json
import urllib2
import git_submodule as GitSubmodule
-chromium_version = '49.0.2623.111'
-chromium_branch = '2623'
-ninja_version = 'v1.6.0'
+chromium_version = '53.0.2785.117'
+chromium_branch = '2785'
+ninja_version = 'v1.7.1'
json_url = 'http://omahaproxy.appspot.com/all.json'
diff --git a/tools/scripts/windeploy-examples.py b/tools/scripts/windeploy-examples.py
new file mode 100755
index 000000000..c41a5bc31
--- /dev/null
+++ b/tools/scripts/windeploy-examples.py
@@ -0,0 +1,393 @@
+#!/usr/bin/env python
+
+#############################################################################
+#
+# Copyright (C) 2015 The Qt Company Ltd.
+# Contact: http://www.qt.io/licensing/
+#
+# This file is part of the QtWebEngine module of the Qt Toolkit.
+#
+# $QT_BEGIN_LICENSE:LGPL$
+# Commercial License Usage
+# Licensees holding valid commercial Qt licenses may use this file in
+# accordance with the commercial license agreement provided with the
+# Software or, alternatively, in accordance with the terms contained in
+# a written agreement between you and The Qt Company. For licensing terms
+# and conditions see http://www.qt.io/terms-conditions. For further
+# information use the contact form at http://www.qt.io/contact-us.
+#
+# GNU Lesser General Public License Usage
+# Alternatively, this file may be used under the terms of the GNU Lesser
+# General Public License version 2.1 as published by the Free Software
+# Foundation and appearing in the file LICENSE.LGPL included in the
+# packaging of this file. Please review the following information to
+# ensure the GNU Lesser General Public License version 2.1 requirements
+# will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+#
+# As a special exception, The Qt Company gives you certain additional
+# rights. These rights are described in The Qt Company LGPL Exception
+# version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+#
+# GNU General Public License Usage
+# Alternatively, this file may be used under the terms of the GNU
+# General Public License version 3.0 as published by the Free Software
+# Foundation and appearing in the file LICENSE.GPL included in the
+# packaging of this file. Please review the following information to
+# ensure the GNU General Public License version 3.0 requirements will be
+# met: http://www.gnu.org/copyleft/gpl.html.
+#
+#
+# $QT_END_LICENSE$
+#
+#############################################################################
+
+import argparse
+import os
+import re
+import subprocess
+import shutil
+import sys
+
+
+class Api:
+ QUICK = "webengine"
+ WIDGET = "webenginewidgets"
+
+
+class Mode:
+ RELEASE = "release"
+ DEBUG = "debug"
+
+
+def is_windows():
+ return os.name == "nt"
+
+
+class ArgManager(object):
+ def __init__(self):
+ try:
+ self.__args = self.__parse()
+ except:
+ raise
+
+ self.build_dir = self.__args.build_dir
+ self.src_dir = self.__args.src_dir
+ self.example_filter = re.compile("%s-%s-%s" % (self.__api_filter(), self.__name_filter(), self.__mode_filter()))
+ self.list_examples = self.__args.list_examples
+ self.force = self.__args.force
+ self.verbose = self.__args.verbose
+ self.out_dir = self.__args.out_dir
+
+ def __parse(self):
+ ap = argparse.ArgumentParser(description="Deploy QtWebEngine example binaries on Windows.")
+ ap.add_argument("--release", dest="release", action="store_true", default=False,
+ help="Deploy release binaries only")
+ ap.add_argument("--debug", dest="debug", action="store_true", default=False,
+ help="Deploy debug binaries only")
+ ap.add_argument("--quick", dest="quick", action="store_true", default=False,
+ help="Deploy quick examples only")
+ ap.add_argument("--widget", dest="widget", action="store_true", default=False,
+ help="Deploy widget examples only")
+ ap.add_argument("-e", "--examples", dest="examples", nargs="+", action="store", default=".*",
+ help="Select example to deploy")
+ ap.add_argument("-l", "--list-examples", dest="list_examples", action="store_true", default=False,
+ help="List available examples")
+ ap.add_argument("-f", "--force", dest="force", action="store_true", default=False,
+ help="Force to overwrite existing files")
+ ap.add_argument("-v", "--verbose", dest="verbose", action="store_true", default=False,
+ help="Print windeployqt output")
+ ap.add_argument("--src-dir", dest="src_dir", action="store", type=self.__validate_src_dir, default=None,
+ help="Specify path of Qt sources. It is used for finding QML files of the example"
+ "and scanning for QML imports")
+ ap.add_argument("--build-dir", dest="build_dir", action="store", type=self.__validate_build_dir, default=None,
+ help="Specify path of the Qt binaries. It is used for finding qmake.exe, windeployqt.exe and"
+ "binaries of the examples. It is not necessary to set if qmake.exe is set in the path")
+ ap.add_argument("-o", "--out-dir", dest="out_dir", action="store", default=os.getcwd(),
+ help="Specify path for the deployed examples. If it is not set"
+ "current working directory is used")
+ return ap.parse_args()
+
+ def __validate_src_dir(self, src_dir):
+ if not os.path.exists(src_dir):
+ raise OSError("The specified Qt source directory does not exist: %s" % src_dir)
+
+ qtwebengine_dir = src_dir
+ # Accept Qt top level source directory too
+ if os.path.exists(os.path.join(src_dir, "qtwebengine")):
+ qtwebengine_dir = os.path.join(src_dir, "qtwebengine")
+
+ examples_dir = os.path.join(qtwebengine_dir, "examples")
+ must_have_paths = [
+ os.path.join(examples_dir, "examples.pro"),
+ os.path.join(examples_dir, Api.QUICK),
+ os.path.join(examples_dir, Api.WIDGET),
+ ]
+
+ # Check whether src_dir is the proper QtWebEngine source directory
+ for p in must_have_paths:
+ if not os.path.exists(p):
+ raise OSError("The specified Qt source directory is invalid: %s" % src_dir)
+
+ return src_dir
+
+ def __validate_build_dir(self, build_dir):
+ if not os.path.exists(build_dir):
+ raise OSError("The specified Qt build directory does not exist: %s" % build_dir)
+
+ # Accept QtWebEngine build directory too
+ if os.path.basename(build_dir) == "qtwebengine":
+ build_dir = os.path.abspath(os.path.join(build_dir, ".."))
+
+ # Attempt to support custom build directories
+ if os.path.exists(os.path.join(build_dir, "bin", "qmake.exe")):
+ return build_dir
+
+ # Check existence of qtbase/bin/qmake.exe
+ qtbase_dir = os.path.join(build_dir, "qtbase")
+ if not os.path.exists(os.path.join(qtbase_dir, "bin", "qmake.exe")):
+ raise OSError("Program 'qmake.exe' cannot be found in the specified Qt build directory: %s" % build_dir)
+
+ return qtbase_dir
+
+ def __mode_filter(self):
+ if self.__args.release and not self.__args.debug:
+ return Mode.RELEASE
+ if not self.__args.release and self.__args.debug:
+ return Mode.DEBUG
+ return ".*"
+
+ def __api_filter(self):
+ if self.__args.quick and not self.__args.widget:
+ return Api.QUICK
+ if not self.__args.quick and self.__args.widget:
+ return Api.WIDGET
+ return ".*"
+
+ def __name_filter(self):
+ alt_list = []
+
+ examples = self.__args.examples
+ if not isinstance(examples, list):
+ examples = [examples]
+
+ for e in examples:
+ if "," in e:
+ alt_list.extend(e.split(","))
+ else:
+ alt_list.append(e)
+
+ return "|".join(alt_list)
+
+
+class QtHelper(object):
+ def __init__(self, build_path=None, src_path=None):
+ self.__build_path = build_path if build_path is not None else ""
+ self.__src_path = src_path if src_path is not None else ""
+ self.__query = {}
+ self.__angle = None
+
+ self.__qmake = "qmake.exe"
+ self.__windeployqt = "windeployqt.exe"
+ if build_path:
+ self.__qmake = os.path.join(self.__build_path, "bin", self.__qmake)
+ self.__windeployqt = os.path.join(self.__build_path, "bin", self.__windeployqt)
+
+ try:
+ program = self.__qmake
+ subprocess.check_output([program, "-v"])
+ program = self.__windeployqt
+ subprocess.check_output([program, "-h"])
+ except OSError as e:
+ raise OSError("Program '%s' cannot be executed\n%s" % (program, e))
+ except:
+ raise
+
+ self.__query = self.get_query()
+ self.__build_path = self.get_build_path()
+ self.__src_path = self.get_src_path()
+ self.__angle = self.has_angle()
+
+ def get_query(self):
+ if self.__query:
+ return self.__query
+
+ qmake_output = subprocess.check_output([self.__qmake, "-query"]).split("\r\n")
+ query = {}
+ for line in qmake_output:
+ entry = line.split(":", 1)
+ if len(entry) != 2:
+ continue
+ query[entry[0]] = entry[1]
+ return query
+
+ def get_build_path(self):
+ return os.path.abspath(os.path.join(self.__query["QT_INSTALL_PREFIX"], ".."))
+
+ def get_src_path(self):
+ if self.__src_path:
+ return self.__src_path
+
+ if "QT_INSTALL_PREFIX/src" in self.__query:
+ return os.path.abspath(os.path.join(self.__query["QT_INSTALL_PREFIX/src"], ".."))
+
+ return self.__build_path
+
+ def get_windeployqt(self):
+ return self.__windeployqt
+
+ def has_angle(self):
+ if self.__angle:
+ return self.__angle
+
+ qconfig_pri_path = os.path.abspath(os.path.join(self.__query["QT_HOST_PREFIX"], "mkspecs", "qconfig.pri"))
+ print(qconfig_pri_path)
+ if not os.path.exists(qconfig_pri_path):
+ sys.stderr.write("Configuration file qconfig.pri cannot be found. Fallback to desktop GL mode.\n")
+ return False
+
+ qt_config = []
+
+ qconfig_pri = open(qconfig_pri_path, "r")
+ for line in qconfig_pri:
+ if line.startswith("QT_CONFIG +="):
+ qt_config = re.match("^QT_CONFIG \+= (.+)$", line).group(1).split(" ")
+ qconfig_pri.close()
+
+ return "angle" in qt_config
+
+ def collect_examples(self):
+ examples = []
+
+ for api in [Api.QUICK, Api.WIDGET]:
+ examples_root_dir_path = os.path.join(self.__build_path, "qtwebengine", "examples", api)
+ if not os.path.exists(examples_root_dir_path):
+ continue
+
+ for example in os.listdir(examples_root_dir_path):
+ example_dir_path = os.path.join(examples_root_dir_path, example)
+ if not os.path.exists(example_dir_path):
+ continue
+
+ example_src_path = os.path.join(self.__src_path, "qtwebengine", "examples", api, example)
+
+ for mode in [Mode.RELEASE, Mode.DEBUG]:
+ example_exe_path = os.path.join(example_dir_path, mode, example + ".exe")
+ if not os.path.exists(example_exe_path):
+ continue
+ examples.append(Example(example, api, mode, self.__angle, example_exe_path, example_src_path))
+
+ return examples
+
+
+class Example(str):
+ def __new__(cls, example, api, mode, angle, exe_path, src_path):
+ obj = str.__new__(cls, "%s-%s-%s" % (api, example, mode))
+ return obj
+
+ def __init__(self, example, api, mode, angle, exe_path, src_path):
+ super(Example, self).__init__("%s-%s-%s" % (api, example, mode))
+ self.__name = example
+ self.__api = api
+ self.__mode = mode
+ self.__angle = angle
+ self.__exe_path = exe_path
+ self.__src_path = src_path
+
+ def get_deploy_params(self, mode, force):
+ deploy_params = []
+ deploy_params.append("--%s" % mode)
+ deploy_params.append("--compiler-runtime")
+
+ if self.__angle:
+ deploy_params.append("--angle")
+
+ if force:
+ deploy_params.append("--force")
+
+ if self.__api is Api.QUICK:
+ deploy_params.append("--qmldir")
+ deploy_params.append(self.__src_path)
+
+ if self.__mode is Mode.DEBUG:
+ deploy_params.append("--pdb")
+
+ return deploy_params
+
+ def name(self):
+ return self.__name
+
+ def deploy(self, qt, dest_path, force=False, verbose=False):
+ src_path = os.path.dirname(self.__exe_path)
+ for f in os.listdir(src_path):
+ shutil.copy(os.path.join(src_path, f), dest_path)
+
+ deploy_command = []
+ deploy_command.append(qt.get_windeployqt())
+ # Debug executables also need the release libraries
+ deploy_command.extend(self.get_deploy_params(Mode.RELEASE, force))
+ deploy_command.append(dest_path)
+
+ if verbose:
+ print("%s" % " ".join(deploy_command))
+
+ out = None if verbose else open(os.devnull, "w")
+ exit_code = subprocess.call(deploy_command, stdout=out)
+
+ if self.__mode is Mode.DEBUG and not exit_code:
+ param_release = "--%s" % Mode.RELEASE
+ param_debug = "--%s" % Mode.DEBUG
+ deploy_command = map(lambda item: param_debug if item == param_release else item, deploy_command)
+
+ if verbose:
+ print("%s" % " ".join(deploy_command))
+
+ exit_code = subprocess.call(deploy_command, stdout=out)
+
+ if out is not None:
+ out.close()
+
+ return exit_code
+
+
+def main():
+ try:
+ args = ArgManager()
+
+ if not is_windows():
+ raise OSError("This script works on Windows only\n")
+
+ qt = QtHelper(args.build_dir, args.src_dir)
+ except Exception as e:
+ sys.stderr.write(str(e))
+ exit(1)
+
+ example_list = filter((lambda e: args.example_filter.match(e)), qt.collect_examples())
+ if not example_list:
+ print("There is no example that fulfills the requirements")
+ return
+
+ for example in example_list:
+ if args.list_examples:
+ print(example.name())
+ continue
+
+ print("Deploying %s ..." % example.name())
+ dest_path = os.path.abspath(os.path.join(args.out_dir, example.name()))
+ if not os.path.exists(dest_path):
+ os.makedirs(dest_path)
+ elif os.listdir(dest_path) and not args.force:
+ sys.stderr.write("Destination directory is not empty: %s\n" % dest_path)
+ sys.stderr.write("Skip deploying %s\n" % example.name())
+ continue
+
+ exit_code = example.deploy(qt, dest_path, args.force, args.verbose)
+ if exit_code:
+ sys.stderr.write("Deploy of example '%s' has failed: %s\n" % (example.name(), exit_code))
+ exit(exit_code)
+
+ print("Example '%s' has been successfully deployed at %s" % (example.name(), dest_path))
+
+ return
+
+if __name__ == "__main__":
+ main()