summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.json1
-rw-r--r--dist/changes-5.11.0121
-rw-r--r--examples/webenginewidgets/contentmanipulation/main.cpp1
-rw-r--r--examples/webenginewidgets/cookiebrowser/main.cpp1
-rw-r--r--examples/webenginewidgets/maps/main.cpp1
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/index.html2
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc1
-rw-r--r--examples/webenginewidgets/markdowneditor/resources/qwebchannel.js430
-rw-r--r--examples/webenginewidgets/simplebrowser/main.cpp4
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/main.cpp3
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp38
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/mainwindow.h2
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/mainwindow.ui56
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp50
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h4
-rw-r--r--examples/webenginewidgets/videoplayer/main.cpp1
-rw-r--r--src/core/api/qwebenginecookiestore.cpp12
-rw-r--r--src/core/api/qwebenginecookiestore.h4
-rw-r--r--src/core/content_browser_client_qt.cpp30
-rw-r--r--src/core/content_browser_client_qt.h2
-rw-r--r--src/core/content_client_qt.cpp1
-rw-r--r--src/core/gl_surface_qt.cpp24
-rw-r--r--src/core/printing/pdfium_document_wrapper_qt.cpp7
-rw-r--r--src/core/printing/pdfium_document_wrapper_qt.h4
-rw-r--r--src/core/quota_request_controller_impl.cpp5
-rw-r--r--src/core/quota_request_controller_impl.h2
-rw-r--r--src/core/register_protocol_handler_request_controller_impl.cpp5
-rw-r--r--src/core/register_protocol_handler_request_controller_impl.h2
-rw-r--r--src/core/render_widget_host_view_qt.cpp98
-rw-r--r--src/core/render_widget_host_view_qt.h2
-rw-r--r--src/core/renderer/user_resource_controller.cpp9
-rw-r--r--src/core/renderer/web_channel_ipc_transport.cpp38
-rw-r--r--src/core/renderer_host/web_channel_ipc_transport_host.cpp17
-rw-r--r--src/core/request_controller.h5
-rw-r--r--src/core/user_script.cpp11
-rw-r--r--src/core/user_script.h2
-rw-r--r--src/core/web_contents_adapter_client.h1
-rw-r--r--src/core/web_contents_delegate_qt.cpp24
-rw-r--r--src/core/web_contents_delegate_qt.h1
-rw-r--r--src/core/web_contents_view_qt.cpp6
-rw-r--r--src/webengine/api/qquickwebengineview.cpp7
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h1
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp10
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h1
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp3
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp4
-rw-r--r--tests/auto/quick/qmltests/data/script-with-bad-match-metadata.js9
-rw-r--r--tests/auto/quick/qmltests/data/tst_userScripts.qml17
-rw-r--r--tests/auto/widgets/origins/resources/dedicatedWorker.html19
-rw-r--r--tests/auto/widgets/origins/resources/dedicatedWorker.js1
-rw-r--r--tests/auto/widgets/origins/resources/serviceWorker.html14
-rw-r--r--tests/auto/widgets/origins/resources/serviceWorker.js1
-rw-r--r--tests/auto/widgets/origins/resources/sharedWorker.html19
-rw-r--r--tests/auto/widgets/origins/resources/sharedWorker.js6
-rw-r--r--tests/auto/widgets/origins/tst_origins.cpp72
-rw-r--r--tests/auto/widgets/origins/tst_origins.qrc6
-rw-r--r--tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp1
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp32
-rw-r--r--tests/auto/widgets/qwebenginescript/resources/webChannelWithBadString.html14
-rw-r--r--tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp22
-rw-r--r--tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc1
-rw-r--r--tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp35
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp178
-rw-r--r--tests/auto/widgets/resources/qwebchannel.js408
-rw-r--r--tests/auto/widgets/resources/tests.qrc5
-rw-r--r--tests/auto/widgets/tests.pri1
66 files changed, 940 insertions, 975 deletions
diff --git a/configure.json b/configure.json
index cd8098c56..723730fb7 100644
--- a/configure.json
+++ b/configure.json
@@ -214,6 +214,7 @@
"webengine-host-compiler": {
"label": "host compiler",
"test": "hostcompiler",
+ "host": "true",
"type": "compile"
},
"webengine-khr": {
diff --git a/dist/changes-5.11.0 b/dist/changes-5.11.0
new file mode 100644
index 000000000..cf721de9f
--- /dev/null
+++ b/dist/changes-5.11.0
@@ -0,0 +1,121 @@
+Qt 5.11 introduces many new features and improvements as well as bugfixes
+over the 5.10.x series. For more details, refer to the online documentation
+included in this distribution. The documentation is also available online:
+
+http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.11 series is binary compatible with the 5.10.x series.
+Applications compiled for 5.10 will continue to run with 5.11.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* General *
+****************************************************************************
+
+Chromium Snapshot
+-----------------
+
+- Updated the Chromium version to 65.0.3325.151.
+- Applied security fixes from Chrome up to version 66.0.3359.139.
+ * Including: CVE-2018-6085, CVE-2018-6086, CVE-2018-6087, CVE-2018-6088,
+ CVE-2018-6089, CVE-2018-6090, CVE-2018-6091, CVE-2018-6092,
+ CVE-2018-6093, CVE-2018-6094, CVE-2018-6096, CVE-2018-6099,
+ CVE-2018-6100, CVE-2018-6101, CVE-2018-6102, CVE-2018-6103,
+ CVE-2018-6104, CVE-2018-6105, CVE-2018-6106, CVE-2018-6108,
+ CVE-2018-6110, CVE-2018-6111, CVE-2018-6115, CVE-2018-6116 and
+ CVE-2018-6118
+
+Behavioral Changes
+------------------
+
+- [QTBUG-65484] User script metadata parsing now supports regular
+ expressions in @include and @exclude rules.
+- Enabled chrome://quota-internals, chrome://taskscheduler-internals,
+ and on Linux, chrome://sandbox.
+- [QTBUG-62414] Default context menus for Qt Quick and Qt Widgets got
+ a revamp and are now unified.
+
+Build System
+------------
+
+- [QTBUG-66596] QtWebEngine now requires Visual Studio 2017 on Windows.
+- Building with -no-feature-draganddrop configure option got fixed.
+
+Command Line
+------------
+
+- Process per Site model is now supported via --process-per-site.
+- There's now an option to hide internal IP addresses from WebRTC via
+ --force-webrtc-ip-handling-policy=default_public_interface_only.
+
+****************************************************************************
+* Libraries *
+****************************************************************************
+
+Deprecation Notice
+------------------
+
+- [QTBUG-62640] [Q]WebEngineDownloadItem::type got deprecated. Use newly
+ introduced [Q]WebEngineDownloadItem::isSavePageDownload instead.
+
+Qt WebEngineCore
+----------------
+
+- [QTBUG-62897] Added QWebEngineCookieStore::setCookieFilter()
+ to allow blocking cookie access.
+- Added QWebEngineQuotaRequest, QWebEngineQuotaRequest classes.
+- Added QWebEngineUrlRequestJob::initiator() accessor.
+
+Qt WebEngine (QML)
+------------------
+
+- Added WebEngineContextMenuRequest::editFlags,
+ WebEngineContextMenuRequest::mediaFlags properties to allow further tailoring
+ custom context menus.
+- [QTBUG-57505] Added WebEngineSettings::webRTCPublicInterfacesOnly property
+ to enable hiding private IP addresses from WebRTC services.
+- [QTBUG-64056] Added WebEngineSettings::javaScriptCanPaste property
+ to enable 'execCommand("paste")'.
+- Added WebEngineSettings::playbackRequiresUserGesture property
+ to inhibit playback of media content until the user interacts with the page.
+- Added WebEngineSettings::unknownUrlSchemePolicy property
+ to specify how navigation requests to URLs with unknown schemes should be
+ handled.
+- [QTBUG-51181] Added WebEngineView.geometryChangeRequested signal.
+- [QTBUG-47899, QTBUG-50725, QTBUG-50766] WebEngineView::inspectedView,
+ WebEngineView::devToolsView properties can be used to programmatically set up
+ a devtools page.
+- Added WebEngineView::quotaRequested() signal to handle requests for bigger
+ file system quotas (navigator.webkitPersistentStorage.requestQuota).
+- Added WebEngineView::registerProtocolHandlerRequested() signal to handle
+ requests from window.navigator.registerProtocolHandler API.
+
+Qt WebEngineWidgets
+-------------------
+
+- Added QWebEngineContextMenuData::editFlags(),
+ QWebEngineContextMenuData::mediaFlags() properties to allow further tailoring
+ custom context menus.
+- [QTBUG-57505] Added QWebEngineSettings::WebRTCPublicInterfacesOnly attribute
+ to enable hiding private IP addresses from WebRTC services.
+- [QTBUG-64056] Added QWebEngineSettings::JavaScriptCanPaste attribute
+ to enable 'execCommand("paste")'.
+- Added QWebEngineSettings::PlaybackRequiresUserGesture attribute
+ to inhibit playback of media content until the user interacts with the page.
+- Added QWebEngineSettings::unknownUrlSchemePolicy property
+ to specify how navigation requests to URLs with unknown schemes should be
+ handled.
+- [QTBUG-47899, QTBUG-50725, QTBUG-50766] QWebEnginePage::setInspectedPage(),
+ QWebEnginePage::setDevToolsPage() can be set to programmatically set up
+ a devtools page.
+- Added QWebEnginePage::quotaRequested() signal to handle requests for bigger
+ file system quotas (navigator.webkitPersistentStorage.requestQuota).
+- Added QWebEnginePage::registerProtocolHandlerRequested() signal to handle
+ requests from window.navigator.registerProtocolHandler API.
diff --git a/examples/webenginewidgets/contentmanipulation/main.cpp b/examples/webenginewidgets/contentmanipulation/main.cpp
index 5645f9b9a..e816079d2 100644
--- a/examples/webenginewidgets/contentmanipulation/main.cpp
+++ b/examples/webenginewidgets/contentmanipulation/main.cpp
@@ -63,6 +63,7 @@ int main(int argc, char * argv[])
else
url = QUrl("http://www.google.com/ncr");
MainWindow *browser = new MainWindow(url);
+ browser->resize(1024, 768);
browser->show();
return app.exec();
}
diff --git a/examples/webenginewidgets/cookiebrowser/main.cpp b/examples/webenginewidgets/cookiebrowser/main.cpp
index ae208c824..0ae5433ba 100644
--- a/examples/webenginewidgets/cookiebrowser/main.cpp
+++ b/examples/webenginewidgets/cookiebrowser/main.cpp
@@ -57,6 +57,7 @@ int main(int argc, char *argv[])
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
MainWindow window(QUrl("http://qt.io"));
+ window.resize(1024, 768);
window.show();
return app.exec();
}
diff --git a/examples/webenginewidgets/maps/main.cpp b/examples/webenginewidgets/maps/main.cpp
index f62518274..cad9c7ea9 100644
--- a/examples/webenginewidgets/maps/main.cpp
+++ b/examples/webenginewidgets/maps/main.cpp
@@ -57,6 +57,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
MainWindow mainWindow;
+ mainWindow.resize(1024, 768);
mainWindow.show();
return app.exec();
diff --git a/examples/webenginewidgets/markdowneditor/resources/index.html b/examples/webenginewidgets/markdowneditor/resources/index.html
index 8623a0642..5fa28fa17 100644
--- a/examples/webenginewidgets/markdowneditor/resources/index.html
+++ b/examples/webenginewidgets/markdowneditor/resources/index.html
@@ -4,7 +4,7 @@
<head>
<link rel="stylesheet" type="text/css" href="3rdparty/markdown.css">
<script src="3rdparty/marked.min.js"></script>
- <script src="qwebchannel.js"></script>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<div id="placeholder"></div>
diff --git a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc
index 9a6bd3801..812c8850a 100644
--- a/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc
+++ b/examples/webenginewidgets/markdowneditor/resources/markdowneditor.qrc
@@ -1,7 +1,6 @@
<RCC>
<qresource prefix="/">
<file>index.html</file>
- <file>qwebchannel.js</file>
<file>3rdparty/marked.min.js</file>
<file>default.md</file>
<file>3rdparty/markdown.css</file>
diff --git a/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js b/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js
deleted file mode 100644
index 8ebfbb1c9..000000000
--- a/examples/webenginewidgets/markdowneditor/resources/qwebchannel.js
+++ /dev/null
@@ -1,430 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebChannel module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-"use strict";
-
-var QWebChannelMessageTypes = {
- signal: 1,
- propertyUpdate: 2,
- init: 3,
- idle: 4,
- debug: 5,
- invokeMethod: 6,
- connectToSignal: 7,
- disconnectFromSignal: 8,
- setProperty: 9,
- response: 10,
-};
-
-var QWebChannel = function(transport, initCallback)
-{
- if (typeof transport !== "object" || typeof transport.send !== "function") {
- console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." +
- " Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send));
- return;
- }
-
- var channel = this;
- this.transport = transport;
-
- this.send = function(data)
- {
- if (typeof(data) !== "string") {
- data = JSON.stringify(data);
- }
- channel.transport.send(data);
- }
-
- this.transport.onmessage = function(message)
- {
- var data = message.data;
- if (typeof data === "string") {
- data = JSON.parse(data);
- }
- switch (data.type) {
- case QWebChannelMessageTypes.signal:
- channel.handleSignal(data);
- break;
- case QWebChannelMessageTypes.response:
- channel.handleResponse(data);
- break;
- case QWebChannelMessageTypes.propertyUpdate:
- channel.handlePropertyUpdate(data);
- break;
- default:
- console.error("invalid message received:", message.data);
- break;
- }
- }
-
- this.execCallbacks = {};
- this.execId = 0;
- this.exec = function(data, callback)
- {
- if (!callback) {
- // if no callback is given, send directly
- channel.send(data);
- return;
- }
- if (channel.execId === Number.MAX_VALUE) {
- // wrap
- channel.execId = Number.MIN_VALUE;
- }
- if (data.hasOwnProperty("id")) {
- console.error("Cannot exec message with property id: " + JSON.stringify(data));
- return;
- }
- data.id = channel.execId++;
- channel.execCallbacks[data.id] = callback;
- channel.send(data);
- };
-
- this.objects = {};
-
- this.handleSignal = function(message)
- {
- var object = channel.objects[message.object];
- if (object) {
- object.signalEmitted(message.signal, message.args);
- } else {
- console.warn("Unhandled signal: " + message.object + "::" + message.signal);
- }
- }
-
- this.handleResponse = function(message)
- {
- if (!message.hasOwnProperty("id")) {
- console.error("Invalid response message received: ", JSON.stringify(message));
- return;
- }
- channel.execCallbacks[message.id](message.data);
- delete channel.execCallbacks[message.id];
- }
-
- this.handlePropertyUpdate = function(message)
- {
- for (var i in message.data) {
- var data = message.data[i];
- var object = channel.objects[data.object];
- if (object) {
- object.propertyUpdate(data.signals, data.properties);
- } else {
- console.warn("Unhandled property update: " + data.object + "::" + data.signal);
- }
- }
- channel.exec({type: QWebChannelMessageTypes.idle});
- }
-
- this.debug = function(message)
- {
- channel.send({type: QWebChannelMessageTypes.debug, data: message});
- };
-
- channel.exec({type: QWebChannelMessageTypes.init}, function(data) {
- for (var objectName in data) {
- var object = new QObject(objectName, data[objectName], channel);
- }
- // now unwrap properties, which might reference other registered objects
- for (var objectName in channel.objects) {
- channel.objects[objectName].unwrapProperties();
- }
- if (initCallback) {
- initCallback(channel);
- }
- channel.exec({type: QWebChannelMessageTypes.idle});
- });
-};
-
-function QObject(name, data, webChannel)
-{
- this.__id__ = name;
- webChannel.objects[name] = this;
-
- // List of callbacks that get invoked upon signal emission
- this.__objectSignals__ = {};
-
- // Cache of all properties, updated when a notify signal is emitted
- this.__propertyCache__ = {};
-
- var object = this;
-
- // ----------------------------------------------------------------------
-
- this.unwrapQObject = function(response)
- {
- if (response instanceof Array) {
- // support list of objects
- var ret = new Array(response.length);
- for (var i = 0; i < response.length; ++i) {
- ret[i] = object.unwrapQObject(response[i]);
- }
- return ret;
- }
- if (!response
- || !response["__QObject*__"]
- || response.id === undefined) {
- return response;
- }
-
- var objectId = response.id;
- if (webChannel.objects[objectId])
- return webChannel.objects[objectId];
-
- if (!response.data) {
- console.error("Cannot unwrap unknown QObject " + objectId + " without data.");
- return;
- }
-
- var qObject = new QObject( objectId, response.data, webChannel );
- qObject.destroyed.connect(function() {
- if (webChannel.objects[objectId] === qObject) {
- delete webChannel.objects[objectId];
- // reset the now deleted QObject to an empty {} object
- // just assigning {} though would not have the desired effect, but the
- // below also ensures all external references will see the empty map
- // NOTE: this detour is necessary to workaround QTBUG-40021
- var propertyNames = [];
- for (var propertyName in qObject) {
- propertyNames.push(propertyName);
- }
- for (var idx in propertyNames) {
- delete qObject[propertyNames[idx]];
- }
- }
- });
- // here we are already initialized, and thus must directly unwrap the properties
- qObject.unwrapProperties();
- return qObject;
- }
-
- this.unwrapProperties = function()
- {
- for (var propertyIdx in object.__propertyCache__) {
- object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]);
- }
- }
-
- function addSignal(signalData, isPropertyNotifySignal)
- {
- var signalName = signalData[0];
- var signalIndex = signalData[1];
- object[signalName] = {
- connect: function(callback) {
- if (typeof(callback) !== "function") {
- console.error("Bad callback given to connect to signal " + signalName);
- return;
- }
-
- object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
- object.__objectSignals__[signalIndex].push(callback);
-
- if (!isPropertyNotifySignal && signalName !== "destroyed") {
- // only required for "pure" signals, handled separately for properties in propertyUpdate
- // also note that we always get notified about the destroyed signal
- webChannel.exec({
- type: QWebChannelMessageTypes.connectToSignal,
- object: object.__id__,
- signal: signalIndex
- });
- }
- },
- disconnect: function(callback) {
- if (typeof(callback) !== "function") {
- console.error("Bad callback given to disconnect from signal " + signalName);
- return;
- }
- object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
- var idx = object.__objectSignals__[signalIndex].indexOf(callback);
- if (idx === -1) {
- console.error("Cannot find connection of signal " + signalName + " to " + callback.name);
- return;
- }
- object.__objectSignals__[signalIndex].splice(idx, 1);
- if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === 0) {
- // only required for "pure" signals, handled separately for properties in propertyUpdate
- webChannel.exec({
- type: QWebChannelMessageTypes.disconnectFromSignal,
- object: object.__id__,
- signal: signalIndex
- });
- }
- }
- };
- }
-
- /**
- * Invokes all callbacks for the given signalname. Also works for property notify callbacks.
- */
- function invokeSignalCallbacks(signalName, signalArgs)
- {
- var connections = object.__objectSignals__[signalName];
- if (connections) {
- connections.forEach(function(callback) {
- callback.apply(callback, signalArgs);
- });
- }
- }
-
- this.propertyUpdate = function(signals, propertyMap)
- {
- // update property cache
- for (var propertyIndex in propertyMap) {
- var propertyValue = propertyMap[propertyIndex];
- object.__propertyCache__[propertyIndex] = propertyValue;
- }
-
- for (var signalName in signals) {
- // Invoke all callbacks, as signalEmitted() does not. This ensures the
- // property cache is updated before the callbacks are invoked.
- invokeSignalCallbacks(signalName, signals[signalName]);
- }
- }
-
- this.signalEmitted = function(signalName, signalArgs)
- {
- invokeSignalCallbacks(signalName, signalArgs);
- }
-
- function addMethod(methodData)
- {
- var methodName = methodData[0];
- var methodIdx = methodData[1];
- object[methodName] = function() {
- var args = [];
- var callback;
- for (var i = 0; i < arguments.length; ++i) {
- if (typeof arguments[i] === "function")
- callback = arguments[i];
- else
- args.push(arguments[i]);
- }
-
- webChannel.exec({
- "type": QWebChannelMessageTypes.invokeMethod,
- "object": object.__id__,
- "method": methodIdx,
- "args": args
- }, function(response) {
- if (response !== undefined) {
- var result = object.unwrapQObject(response);
- if (callback) {
- (callback)(result);
- }
- }
- });
- };
- }
-
- function bindGetterSetter(propertyInfo)
- {
- var propertyIndex = propertyInfo[0];
- var propertyName = propertyInfo[1];
- var notifySignalData = propertyInfo[2];
- // initialize property cache with current value
- // NOTE: if this is an object, it is not directly unwrapped as it might
- // reference other QObject that we do not know yet
- object.__propertyCache__[propertyIndex] = propertyInfo[3];
-
- if (notifySignalData) {
- if (notifySignalData[0] === 1) {
- // signal name is optimized away, reconstruct the actual name
- notifySignalData[0] = propertyName + "Changed";
- }
- addSignal(notifySignalData, true);
- }
-
- Object.defineProperty(object, propertyName, {
- configurable: true,
- get: function () {
- var propertyValue = object.__propertyCache__[propertyIndex];
- if (propertyValue === undefined) {
- // This shouldn't happen
- console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__);
- }
-
- return propertyValue;
- },
- set: function(value) {
- if (value === undefined) {
- console.warn("Property setter for " + propertyName + " called with undefined value!");
- return;
- }
- object.__propertyCache__[propertyIndex] = value;
- webChannel.exec({
- "type": QWebChannelMessageTypes.setProperty,
- "object": object.__id__,
- "property": propertyIndex,
- "value": value
- });
- }
- });
-
- }
-
- // ----------------------------------------------------------------------
-
- data.methods.forEach(addMethod);
-
- data.properties.forEach(bindGetterSetter);
-
- data.signals.forEach(function(signal) { addSignal(signal, false); });
-
- for (var name in data.enums) {
- object[name] = data.enums[name];
- }
-}
-
-//required for use with nodejs
-if (typeof module === 'object') {
- module.exports = {
- QWebChannel: QWebChannel
- };
-}
diff --git a/examples/webenginewidgets/simplebrowser/main.cpp b/examples/webenginewidgets/simplebrowser/main.cpp
index 9b9bf80b5..96b1eab97 100644
--- a/examples/webenginewidgets/simplebrowser/main.cpp
+++ b/examples/webenginewidgets/simplebrowser/main.cpp
@@ -50,7 +50,7 @@
#include "browser.h"
#include "browserwindow.h"
-#include "webview.h"
+#include "tabwidget.h"
#include <QApplication>
#include <QWebEngineSettings>
@@ -78,7 +78,7 @@ int main(int argc, char **argv)
Browser browser;
BrowserWindow *window = browser.createWindow();
- window->currentTab()->setUrl(url);
+ window->tabWidget()->setUrl(url);
return app.exec();
}
diff --git a/examples/webenginewidgets/stylesheetbrowser/main.cpp b/examples/webenginewidgets/stylesheetbrowser/main.cpp
index 957913f5a..54fce0ce3 100644
--- a/examples/webenginewidgets/stylesheetbrowser/main.cpp
+++ b/examples/webenginewidgets/stylesheetbrowser/main.cpp
@@ -49,6 +49,7 @@
****************************************************************************/
#include "mainwindow.h"
+#include "stylesheetdialog.h"
#include <QApplication>
#include <QUrl>
@@ -58,6 +59,8 @@ int main(int argc, char *argv[])
QCoreApplication::setOrganizationDomain("www.qt.io");
QCoreApplication::setApplicationName("StyleSheet Browser");
+ qRegisterMetaTypeStreamOperators<StyleSheet>("StyleSheet");
+
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication a(argc, argv);
MainWindow w(QUrl("http://qt.io"));
diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp b/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp
index f7e6964cb..c93205b18 100644
--- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp
+++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.cpp
@@ -49,9 +49,12 @@
****************************************************************************/
#include "mainwindow.h"
+#include "stylesheetdialog.h"
#include "ui_mainwindow.h"
-#include "stylesheetdialog.h"
+static QMap<QString, QString> defaultStyleSheets = {
+ {"Upside down", "body { -webkit-transform: rotate(180deg); }"}
+};
MainWindow::MainWindow(const QUrl &url) :
QMainWindow(),
@@ -67,8 +70,16 @@ MainWindow::MainWindow(const QUrl &url) :
QSettings settings;
settings.beginGroup("styleSheets");
QStringList styleSheets = settings.allKeys();
- for (auto name : qAsConst(styleSheets))
- insertStyleSheet(name, settings.value(name, QString()).toString(), false);
+ if (styleSheets.empty()) {
+ // Add back default style sheets if the user cleared them out
+ loadDefaultStyleSheets();
+ } else {
+ for (auto name : qAsConst(styleSheets)) {
+ StyleSheet styleSheet = settings.value(name).value<StyleSheet>();
+ if (styleSheet.second)
+ insertStyleSheet(name, styleSheet.first, false);
+ }
+ }
settings.endGroup();
ui->webEngineView->setUrl(url);
@@ -114,6 +125,27 @@ void MainWindow::removeStyleSheet(const QString &name, bool immediately)
ui->webEngineView->page()->scripts().remove(script);
}
+bool MainWindow::hasStyleSheet(const QString &name)
+{
+ QWebEngineScript script = ui->webEngineView->page()->scripts().findScript(name);
+ return !script.isNull();
+}
+
+void MainWindow::loadDefaultStyleSheets()
+{
+ QSettings settings;
+ settings.beginGroup("styleSheets");
+
+ auto it = defaultStyleSheets.constBegin();
+ while (it != defaultStyleSheets.constEnd()) {
+ settings.setValue(it.key(), QVariant::fromValue(qMakePair(it.value(), true)));
+ insertStyleSheet(it.key(), it.value(), false);
+ ++it;
+ }
+
+ settings.endGroup();
+}
+
void MainWindow::urlEntered()
{
ui->webEngineView->setUrl(QUrl::fromUserInput(ui->urlBar->text()));
diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.h b/examples/webenginewidgets/stylesheetbrowser/mainwindow.h
index fb0c8e7be..c39735af8 100644
--- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.h
+++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.h
@@ -71,6 +71,8 @@ public:
void insertStyleSheet(const QString &name, const QString &source, bool immediately);
void removeStyleSheet(const QString &name, bool immediately);
+ bool hasStyleSheet(const QString &name);
+ void loadDefaultStyleSheets();
private slots:
void urlEntered();
diff --git a/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui b/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui
index f9c1af969..bc68c16bb 100644
--- a/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui
+++ b/examples/webenginewidgets/stylesheetbrowser/mainwindow.ui
@@ -18,11 +18,47 @@
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
<item>
<widget class="QWidget" name="webContentsWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
<item>
<widget class="QWidget" name="urlBarWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLineEdit" name="urlBar"/>
@@ -32,13 +68,13 @@
<property name="text">
<string/>
</property>
- <property name="shortcut">
- <string>Ctrl+R</string>
- </property>
<property name="icon">
<iconset resource="stylesheetbrowser.qrc">
<normaloff>:/view-refresh.png</normaloff>:/view-refresh.png</iconset>
</property>
+ <property name="shortcut">
+ <string>Ctrl+R</string>
+ </property>
</widget>
</item>
<item>
@@ -52,8 +88,14 @@
</widget>
</item>
<item>
- <widget class="QWebEngineView" name="webEngineView">
- <property name="url">
+ <widget class="QWebEngineView" name="webEngineView" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="url" stdset="0">
<url>
<string>about:blank</string>
</url>
@@ -84,6 +126,8 @@
<header location="global">QtWebEngineWidgets/QWebEngineView</header>
</customwidget>
</customwidgets>
- <resources/>
+ <resources>
+ <include location="stylesheetbrowser.qrc"/>
+ </resources>
<connections/>
</ui>
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp
index eb8abe135..7351ab75f 100644
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp
+++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.cpp
@@ -59,6 +59,7 @@ StylesheetDialog::StylesheetDialog(QWidget *parent) :
ui->setupUi(this);
connect(ui->styleSheetList, &QListWidget::currentItemChanged, this, &StylesheetDialog::currentStyleSheetChanged);
+ connect(ui->styleSheetList, &QListWidget::itemClicked, this, &StylesheetDialog::listItemClicked);
connect(ui->fileNameEdit, &QLineEdit::textChanged, this, &StylesheetDialog::fileNameChanged);
connect(ui->addButton, &QPushButton::clicked, this, &StylesheetDialog::addButtonClicked);
@@ -66,8 +67,12 @@ StylesheetDialog::StylesheetDialog(QWidget *parent) :
QSettings settings;
settings.beginGroup("styleSheets");
- for (auto name : settings.allKeys())
- new QListWidgetItem(name, ui->styleSheetList);
+ for (auto name : settings.allKeys()) {
+ QListWidgetItem *listItem = new QListWidgetItem(name, ui->styleSheetList);
+ listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable);
+ bool checked = settings.value(name).value<StyleSheet>().second;
+ listItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
+ }
settings.endGroup();
}
@@ -92,7 +97,33 @@ void StylesheetDialog::currentStyleSheetChanged(QListWidgetItem *current, QListW
QSettings settings;
settings.beginGroup("styleSheets");
ui->fileNameEdit->setText(current->text());
- ui->sourceCodeEdit->setPlainText(settings.value(current->text(), QString()).toString());
+ const QString source = settings.value(current->text()).value<StyleSheet>().first;
+ ui->sourceCodeEdit->setPlainText(source);
+ settings.endGroup();
+}
+
+void StylesheetDialog::listItemClicked(QListWidgetItem *item)
+{
+ MainWindow *window = static_cast<MainWindow *>(parent());
+ const QString name = item->text();
+ bool checkedStateChanged =
+ (item->checkState() == Qt::Checked && !window->hasStyleSheet(name)) ||
+ (item->checkState() == Qt::Unchecked && window->hasStyleSheet(name));
+ if (!checkedStateChanged)
+ return;
+
+ QSettings settings;
+ settings.beginGroup("styleSheets");
+ const QString source = settings.value(name).value<StyleSheet>().first;
+
+ if (item->checkState() == Qt::Checked) {
+ settings.setValue(name, QVariant::fromValue(qMakePair(source, true)));
+ window->insertStyleSheet(name, source, true);
+ } else {
+ settings.setValue(name, QVariant::fromValue(qMakePair(source, false)));
+ window->removeStyleSheet(name, true);
+ }
+
settings.endGroup();
}
@@ -107,16 +138,21 @@ void StylesheetDialog::fileNameChanged(const QString &text)
void StylesheetDialog::addButtonClicked()
{
- new QListWidgetItem(ui->fileNameEdit->text(), ui->styleSheetList);
-
- MainWindow *window = static_cast<MainWindow *>(parent());
const QString name = ui->fileNameEdit->text();
const QString source = ui->sourceCodeEdit->toPlainText();
+ if (name.isEmpty() || source.isEmpty())
+ return;
+
+ QListWidgetItem *listItem = new QListWidgetItem(ui->fileNameEdit->text(), ui->styleSheetList);
+ listItem->setFlags(listItem->flags() | Qt::ItemIsUserCheckable);
+ listItem->setCheckState(Qt::Checked);
+
+ MainWindow *window = static_cast<MainWindow *>(parent());
window->insertStyleSheet(name, source, true);
QSettings settings;
settings.beginGroup("styleSheets");
- settings.setValue(name, source);
+ settings.setValue(name, QVariant::fromValue(qMakePair(source, true)));
settings.endGroup();
ui->addButton->setEnabled(false);
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h
index f65cfe666..3bf3219ca 100644
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h
+++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.h
@@ -60,6 +60,9 @@ class StylesheetDialog;
}
QT_END_NAMESPACE
+typedef QPair<QString, bool> StyleSheet; // <source, isEnabled>
+Q_DECLARE_METATYPE(StyleSheet);
+
class StylesheetDialog : public QDialog
{
Q_OBJECT
@@ -70,6 +73,7 @@ public:
private slots:
void currentStyleSheetChanged(QListWidgetItem *current, QListWidgetItem *previous);
+ void listItemClicked(QListWidgetItem *item);
void fileNameChanged(const QString &text);
void addButtonClicked();
diff --git a/examples/webenginewidgets/videoplayer/main.cpp b/examples/webenginewidgets/videoplayer/main.cpp
index f62518274..cad9c7ea9 100644
--- a/examples/webenginewidgets/videoplayer/main.cpp
+++ b/examples/webenginewidgets/videoplayer/main.cpp
@@ -57,6 +57,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv);
MainWindow mainWindow;
+ mainWindow.resize(1024, 768);
mainWindow.show();
return app.exec();
diff --git a/src/core/api/qwebenginecookiestore.cpp b/src/core/api/qwebenginecookiestore.cpp
index ee82093a5..5fcd46064 100644
--- a/src/core/api/qwebenginecookiestore.cpp
+++ b/src/core/api/qwebenginecookiestore.cpp
@@ -200,7 +200,7 @@ bool QWebEngineCookieStorePrivate::canAccessCookies(const QUrl &firstPartyUrl, c
toGurl(firstPartyUrl),
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- QWebEngineCookieStore::FilterRequest request = { thirdParty, firstPartyUrl, url };
+ QWebEngineCookieStore::FilterRequest request = { firstPartyUrl, url, thirdParty, false, 0};
return filterCallback(request);
}
@@ -400,6 +400,16 @@ void QWebEngineCookieStore::setCookieFilter(std::function<bool(const FilterReque
*/
/*!
+ \variable QWebEngineCookieStore::FilterRequest::_reservedFlag
+ \internal
+*/
+
+/*!
+ \variable QWebEngineCookieStore::FilterRequest::_reservedType
+ \internal
+*/
+
+/*!
\variable QWebEngineCookieStore::FilterRequest::origin
\brief The URL of the script or content accessing a cookie.
diff --git a/src/core/api/qwebenginecookiestore.h b/src/core/api/qwebenginecookiestore.h
index a62765f77..87d7390a3 100644
--- a/src/core/api/qwebenginecookiestore.h
+++ b/src/core/api/qwebenginecookiestore.h
@@ -62,9 +62,11 @@ class QWEBENGINE_EXPORT QWebEngineCookieStore : public QObject {
public:
struct FilterRequest {
- bool thirdParty;
QUrl firstPartyUrl;
QUrl origin;
+ bool thirdParty;
+ bool _reservedFlag;
+ ushort _reservedType;
};
virtual ~QWebEngineCookieStore();
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index 6748fb956..aa13cce3a 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -53,6 +53,7 @@
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/common/url_schemes.h"
#include "content/public/browser/browser_main_parts.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/browser/media_observer.h"
@@ -67,6 +68,7 @@
#include "content/public/common/main_function_params.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/url_constants.h"
+#include "device/geolocation/public/cpp/location_provider.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "printing/features/features.h"
@@ -121,6 +123,10 @@
#include "renderer_host/pepper/pepper_host_factory_qt.h"
#endif
+#if defined(QT_USE_POSITIONING)
+#include "location_provider_qt.h"
+#endif
+
#include <QGuiApplication>
#include <QLocale>
#ifndef QT_NO_OPENGL
@@ -723,6 +729,30 @@ bool ContentBrowserClientQt::CanCreateWindow(
return (settings && settings->getJavaScriptCanOpenWindowsAutomatically()) || user_gesture;
}
+std::unique_ptr<device::LocationProvider> ContentBrowserClientQt::OverrideSystemLocationProvider()
+{
+#if defined(QT_USE_POSITIONING)
+ return base::WrapUnique(new LocationProviderQt());
+#else
+ return nullptr;
+#endif
+}
+
+scoped_refptr<net::URLRequestContextGetter> GetSystemRequestContextOnUIThread()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ return scoped_refptr<net::URLRequestContextGetter>(
+ BrowserContextAdapter::defaultContext()->browserContext()->GetRequestContext());
+}
+
+void ContentBrowserClientQt::GetGeolocationRequestContext(
+ base::OnceCallback<void(scoped_refptr<net::URLRequestContextGetter>)> callback)
+{
+ content::BrowserThread::PostTaskAndReplyWithResult(
+ content::BrowserThread::UI, FROM_HERE,
+ base::BindOnce(&GetSystemRequestContextOnUIThread), std::move(callback));
+}
+
bool ContentBrowserClientQt::AllowGetCookie(const GURL &url,
const GURL &first_party,
const net::CookieList & /*cookie_list*/,
diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h
index 042de5c8c..515574147 100644
--- a/src/core/content_browser_client_qt.h
+++ b/src/core/content_browser_client_qt.h
@@ -168,6 +168,8 @@ public:
content::ResourceContext *context,
const std::vector<std::pair<int, int> > &render_frames) override;
+ std::unique_ptr<device::LocationProvider> OverrideSystemLocationProvider() override;
+ void GetGeolocationRequestContext(base::OnceCallback<void(scoped_refptr<net::URLRequestContextGetter>)> callback) override;
#if defined(Q_OS_LINUX)
void GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings) override;
#endif
diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp
index c1683bfa0..37b601bf8 100644
--- a/src/core/content_client_qt.cpp
+++ b/src/core/content_client_qt.cpp
@@ -276,6 +276,7 @@ void AddPepperWidevine(std::vector<content::PepperPluginInfo>* plugins)
widevine_cdm.mime_types.push_back(widevine_cdm_mime_type);
widevine_cdm.permissions = kWidevineCdmPluginPermissions;
plugins->push_back(widevine_cdm);
+ break;
}
}
#endif // defined(WIDEVINE_CDM_AVAILABLE) && BUILDFLAG(ENABLE_PEPPER_CDMS) &&
diff --git a/src/core/gl_surface_qt.cpp b/src/core/gl_surface_qt.cpp
index 8bfbd865c..0d143ee18 100644
--- a/src/core/gl_surface_qt.cpp
+++ b/src/core/gl_surface_qt.cpp
@@ -72,6 +72,14 @@
#include "ozone/gl_surface_glx_qt.h"
#include "ui/gl/gl_glx_api_implementation.h"
#include <dlfcn.h>
+
+#ifndef QT_NO_OPENGL
+#include <QOpenGLContext>
+QT_BEGIN_NAMESPACE
+Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
+QT_END_NAMESPACE
+#endif
+
#endif
#include "ozone/gl_surface_egl_qt.h"
@@ -195,10 +203,20 @@ bool InitializeStaticGLBindings(GLImplementation implementation) {
reinterpret_cast<GLGetProcAddressProc>(
base::GetFunctionPointerFromNativeLibrary(library,
"glXGetProcAddress"));
+
+#ifndef QT_NO_OPENGL
if (!get_proc_address) {
- LOG(ERROR) << "glxGetProcAddress not found.";
- base::UnloadNativeLibrary(library);
- return false;
+ // glx handle not loaded , fallback to qpa
+ if (QOpenGLContext *context = qt_gl_global_share_context()) {
+ get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(
+ context->getProcAddress("glXGetProcAddress"));
+ }
+ }
+#endif
+ if (!get_proc_address) {
+ LOG(ERROR) << "glxGetProcAddress not found.";
+ base::UnloadNativeLibrary(library);
+ return false;
}
SetGLGetProcAddressProc(get_proc_address);
diff --git a/src/core/printing/pdfium_document_wrapper_qt.cpp b/src/core/printing/pdfium_document_wrapper_qt.cpp
index ca1e8cd07..a7433b2cc 100644
--- a/src/core/printing/pdfium_document_wrapper_qt.cpp
+++ b/src/core/printing/pdfium_document_wrapper_qt.cpp
@@ -37,11 +37,8 @@
**
****************************************************************************/
#include "pdf/features.h"
-#if BUILDFLAG(ENABLE_PDF)
-#define ENABLE_PDF
-#endif
-#if defined(ENABLE_PDF)
+#if BUILDFLAG(ENABLE_PDF)
#include "pdfium_document_wrapper_qt.h"
#include <QtCore/qhash.h>
@@ -168,4 +165,4 @@ PdfiumDocumentWrapperQt::~PdfiumDocumentWrapperQt()
}
}
-#endif // defined (ENABLE_PDF)
+#endif // BUILDFLAG(ENABLE_PDF)
diff --git a/src/core/printing/pdfium_document_wrapper_qt.h b/src/core/printing/pdfium_document_wrapper_qt.h
index 28c490ae5..7886c51c0 100644
--- a/src/core/printing/pdfium_document_wrapper_qt.h
+++ b/src/core/printing/pdfium_document_wrapper_qt.h
@@ -40,11 +40,8 @@
#ifndef PDFIUM_DOCUMENT_WRAPPER_QT_H
#define PDFIUM_DOCUMENT_WRAPPER_QT_H
-#if defined(ENABLE_PDF)
#include "qtwebenginecoreglobal.h"
-#include <QtCore/qglobal.h>
-#include <QtCore/qhash.h>
#include <QtGui/qimage.h>
namespace QtWebEngineCore {
@@ -67,5 +64,4 @@ private:
};
} // namespace QtWebEngineCore
-#endif // defined (ENABLE_PDF)
#endif // PDFIUM_DOCUMENT_WRAPPER_QT_H
diff --git a/src/core/quota_request_controller_impl.cpp b/src/core/quota_request_controller_impl.cpp
index ee94e1cdd..a18ad761d 100644
--- a/src/core/quota_request_controller_impl.cpp
+++ b/src/core/quota_request_controller_impl.cpp
@@ -54,6 +54,11 @@ QuotaRequestControllerImpl::QuotaRequestControllerImpl(
, m_callback(callback)
{}
+QuotaRequestControllerImpl::~QuotaRequestControllerImpl()
+{
+ reject();
+}
+
void QuotaRequestControllerImpl::accepted()
{
m_context->dispatchCallbackOnIOThread(m_callback, QuotaPermissionContextQt::QUOTA_PERMISSION_RESPONSE_ALLOW);
diff --git a/src/core/quota_request_controller_impl.h b/src/core/quota_request_controller_impl.h
index dacdce72f..5814895f3 100644
--- a/src/core/quota_request_controller_impl.h
+++ b/src/core/quota_request_controller_impl.h
@@ -52,6 +52,8 @@ public:
const content::StorageQuotaParams &params,
const content::QuotaPermissionContext::PermissionCallback &callback);
+ ~QuotaRequestControllerImpl();
+
protected:
void accepted() override;
void rejected() override;
diff --git a/src/core/register_protocol_handler_request_controller_impl.cpp b/src/core/register_protocol_handler_request_controller_impl.cpp
index 1e3a15c93..0f24d8812 100644
--- a/src/core/register_protocol_handler_request_controller_impl.cpp
+++ b/src/core/register_protocol_handler_request_controller_impl.cpp
@@ -54,6 +54,11 @@ RegisterProtocolHandlerRequestControllerImpl::RegisterProtocolHandlerRequestCont
, m_handler(handler)
{}
+RegisterProtocolHandlerRequestControllerImpl::~RegisterProtocolHandlerRequestControllerImpl()
+{
+ reject();
+}
+
ProtocolHandlerRegistry *RegisterProtocolHandlerRequestControllerImpl::protocolHandlerRegistry()
{
content::WebContents *webContents = web_contents();
diff --git a/src/core/register_protocol_handler_request_controller_impl.h b/src/core/register_protocol_handler_request_controller_impl.h
index 5ad64210c..64f229ac4 100644
--- a/src/core/register_protocol_handler_request_controller_impl.h
+++ b/src/core/register_protocol_handler_request_controller_impl.h
@@ -57,6 +57,8 @@ public:
content::WebContents *webContents,
ProtocolHandler handler);
+ ~RegisterProtocolHandlerRequestControllerImpl();
+
protected:
void accepted() override;
void rejected() override;
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 66d9b819e..ec3add2f6 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -327,7 +327,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget
, m_adapterClient(0)
, m_rendererCompositorFrameSink(0)
, m_imeInProgress(false)
- , m_receivedEmptyImeText(false)
+ , m_receivedEmptyImeEvent(false)
, m_initPending(false)
, m_beginFrameSource(nullptr)
, m_needsBeginFrames(false)
@@ -1219,22 +1219,20 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev)
if (IsMouseLocked() && ev->key() == Qt::Key_Escape && ev->type() == QEvent::KeyRelease)
UnlockMouse();
- if (m_receivedEmptyImeText) {
+ if (m_receivedEmptyImeEvent) {
// IME composition was not finished with a valid commit string.
// We're getting the composition result in a key event.
if (ev->key() != 0) {
// The key event is not a result of an IME composition. Cancel IME.
m_host->ImeCancelComposition();
- m_receivedEmptyImeText = false;
+ m_receivedEmptyImeEvent = false;
} else {
if (ev->type() == QEvent::KeyRelease) {
- m_receivedEmptyImeText = false;
- m_host->ImeSetComposition(toString16(ev->text()),
- std::vector<ui::ImeTextSpan>(),
- gfx::Range::InvalidRange(),
- gfx::Range::InvalidRange().start(),
- gfx::Range::InvalidRange().end());
- m_host->ImeFinishComposingText(false);
+ m_host->ImeCommitText(toString16(ev->text()),
+ std::vector<ui::ImeTextSpan>(),
+ gfx::Range::InvalidRange(),
+ 0);
+ m_receivedEmptyImeEvent = false;
m_imeInProgress = false;
}
return;
@@ -1365,54 +1363,54 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
}
}
- auto setCompositionString = [&](const QString &compositionString){
- m_host->ImeSetComposition(toString16(compositionString),
- underlines,
- replacementRange,
- selectionRange.start(),
- selectionRange.end());
- };
-
- if (!commitString.isEmpty() || replacementLength > 0) {
- setCompositionString(commitString);
- m_host->ImeFinishComposingText(false);
-
- // We might get a commit string and a pre-edit string in a single event, which means
- // we need to confirm the last composition, and start a new composition.
- if (!preeditString.isEmpty()) {
- setCompositionString(preeditString);
- m_imeInProgress = true;
- } else {
- m_imeInProgress = false;
- }
- m_receivedEmptyImeText = commitString.isEmpty();
- } else if (!preeditString.isEmpty()) {
- setCompositionString(preeditString);
- m_imeInProgress = true;
- m_receivedEmptyImeText = false;
- } else {
- // There are so-far two known cases, when an empty QInputMethodEvent is received.
- // First one happens when backspace is used to remove the last character in the pre-edit
- // string, thus signaling the end of the composition.
- // The second one happens (on Windows) when a Korean char gets composed, but instead of
- // the event having a commit string, both strings are empty, and the actual char is received
- // as a QKeyEvent after the QInputMethodEvent is processed.
- // In lieu of the second case, we can't simply cancel the composition on an empty event,
- // and then add the Korean char when QKeyEvent is received, because that leads to text
- // flickering in the textarea (or any other element).
- // Instead we postpone the processing of the empty QInputMethodEvent by posting it
- // to the same focused object, and cancelling the composition on the next event loop tick.
- if (!m_receivedEmptyImeText && m_imeInProgress && !hasSelection) {
- m_receivedEmptyImeText = true;
+ // There are so-far two known cases, when an empty QInputMethodEvent is received.
+ // First one happens when backspace is used to remove the last character in the pre-edit
+ // string, thus signaling the end of the composition.
+ // The second one happens (on Windows) when a Korean char gets composed, but instead of
+ // the event having a commit string, both strings are empty, and the actual char is received
+ // as a QKeyEvent after the QInputMethodEvent is processed.
+ // In lieu of the second case, we can't simply cancel the composition on an empty event,
+ // and then add the Korean char when QKeyEvent is received, because that leads to text
+ // flickering in the textarea (or any other element).
+ // Instead we postpone the processing of the empty QInputMethodEvent by posting it
+ // to the same focused object, and cancelling the composition on the next event loop tick.
+ if (commitString.isEmpty() && preeditString.isEmpty() && replacementLength == 0) {
+ if (!m_receivedEmptyImeEvent && m_imeInProgress && !hasSelection) {
+ m_receivedEmptyImeEvent = true;
QInputMethodEvent *eventCopy = new QInputMethodEvent(*ev);
QGuiApplication::postEvent(qApp->focusObject(), eventCopy);
} else {
- m_receivedEmptyImeText = false;
+ m_receivedEmptyImeEvent = false;
if (m_imeInProgress) {
m_imeInProgress = false;
m_host->ImeCancelComposition();
}
}
+
+ return;
+ }
+
+ m_receivedEmptyImeEvent = false;
+
+ // Finish compostion: insert or erase text.
+ if (!commitString.isEmpty() || replacementLength > 0) {
+ m_host->ImeCommitText(toString16(commitString),
+ underlines,
+ replacementRange,
+ 0);
+ m_imeInProgress = false;
+ }
+
+ // Update or start new composition.
+ // Be aware of that, we might get a commit string and a pre-edit string in a single event and
+ // this means a new composition.
+ if (!preeditString.isEmpty()) {
+ m_host->ImeSetComposition(toString16(preeditString),
+ underlines,
+ replacementRange,
+ selectionRange.start(),
+ selectionRange.end());
+ m_imeInProgress = true;
}
}
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index db68e5232..2a1485510 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -253,7 +253,7 @@ private:
viz::mojom::CompositorFrameSinkClient *m_rendererCompositorFrameSink;
bool m_imeInProgress;
- bool m_receivedEmptyImeText;
+ bool m_receivedEmptyImeEvent;
QPoint m_previousMousePosition;
bool m_initPending;
diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp
index ebc88c403..50a3924c6 100644
--- a/src/core/renderer/user_resource_controller.cpp
+++ b/src/core/renderer/user_resource_controller.cpp
@@ -69,6 +69,11 @@ 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 int validUserScriptSchemes()
+{
+ return URLPattern::SCHEME_HTTP | URLPattern::SCHEME_HTTPS | URLPattern::SCHEME_FILE;
+}
+
static bool regexMatchesURL(const std::string &pat, const GURL &url) {
QRegularExpression qre(QtWebEngineCore::toQt(pat));
qre.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
@@ -97,8 +102,8 @@ static bool scriptMatchesURL(const UserScriptData &scriptData, const GURL &url)
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))
+ URLPattern urlPattern(validUserScriptSchemes());
+ if (urlPattern.Parse(*it) == URLPattern::PARSE_SUCCESS && urlPattern.MatchesURL(url))
matchFound = true;
}
if (!matchFound)
diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp
index bb544168f..ef00bcef3 100644
--- a/src/core/renderer/web_channel_ipc_transport.cpp
+++ b/src/core/renderer/web_channel_ipc_transport.cpp
@@ -64,7 +64,7 @@ public:
static void Uninstall(blink::WebLocalFrame *frame, uint worldId);
private:
WebChannelTransport() {}
- bool NativeQtSendMessage(gin::Arguments *args);
+ void NativeQtSendMessage(gin::Arguments *args);
// gin::WrappableBase
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate *isolate) override;
@@ -118,37 +118,45 @@ void WebChannelTransport::Uninstall(blink::WebLocalFrame *frame, uint worldId)
qtObject->Delete(gin::StringToV8(isolate, "webChannelTransport"));
}
-bool WebChannelTransport::NativeQtSendMessage(gin::Arguments *args)
+void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args)
{
blink::WebLocalFrame *frame = blink::WebLocalFrame::FrameForCurrentContext();
if (!frame || !frame->View())
- return false;
+ return;
content::RenderFrame *renderFrame = content::RenderFrame::FromWebFrame(frame);
if (!renderFrame)
- return false;
+ return;
+
+ v8::Local<v8::Value> jsonValue;
+ if (!args->GetNext(&jsonValue)) {
+ args->ThrowTypeError("Missing argument");
+ return;
+ }
- std::string message;
- if (!args->GetNext(&message))
- return false;
+ if (!jsonValue->IsString()) {
+ args->ThrowTypeError("Expected string");
+ return;
+ }
+ v8::Local<v8::String> jsonString = v8::Local<v8::String>::Cast(jsonValue);
+
+ QByteArray json(jsonString->Utf8Length(), 0);
+ jsonString->WriteUtf8(json.data(), json.size(),
+ nullptr,
+ v8::String::REPLACE_INVALID_UTF8);
- QByteArray valueData(message.data(), message.size());
QJsonParseError error;
- QJsonDocument doc = QJsonDocument::fromJson(valueData, &error);
+ QJsonDocument doc = QJsonDocument::fromJson(json, &error);
if (error.error != QJsonParseError::NoError) {
- LOG(WARNING) << "Parsing error: " << qPrintable(error.errorString());
- return false;
+ args->ThrowTypeError("Invalid JSON");
+ return;
}
int size = 0;
const char *rawData = doc.rawData(&size);
- if (size == 0)
- return false;
-
renderFrame->Send(new WebChannelIPCTransportHost_SendMessage(
renderFrame->GetRoutingID(),
std::vector<char>(rawData, rawData + size)));
- return true;
}
gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate)
diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp
index 6b32093a6..d99dfde97 100644
--- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp
+++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp
@@ -49,6 +49,8 @@
#include <QJsonObject>
#include <QLoggingCategory>
+#include <QtCore/private/qjson_p.h>
+
namespace QtWebEngineCore {
Q_LOGGING_CATEGORY(log, "qt.webengine.webchanneltransport");
@@ -108,10 +110,19 @@ void WebChannelIPCTransportHost::setWorldId(content::RenderFrameHost *frame, bas
void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector<char> &message)
{
- Q_ASSERT(!message.empty());
- QJsonDocument doc = QJsonDocument::fromRawData(message.data(), message.size(), QJsonDocument::BypassValidation);
- Q_ASSERT(doc.isObject());
content::RenderFrameHost *frame = web_contents()->GetMainFrame();
+
+ QJsonDocument doc;
+ // QJsonDocument::fromRawData does not check the length before it starts
+ // parsing the QJsonPrivate::Header and QJsonPrivate::Base structures.
+ if (message.size() >= sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base))
+ doc = QJsonDocument::fromRawData(message.data(), message.size());
+
+ if (!doc.isObject()) {
+ qCCritical(log).nospace() << "received invalid webchannel message from " << frame;
+ return;
+ }
+
qCDebug(log).nospace() << "received webchannel message from " << frame << ": " << doc;
Q_EMIT messageReceived(doc.object(), this);
}
diff --git a/src/core/request_controller.h b/src/core/request_controller.h
index a15c601d7..ffcf9edac 100644
--- a/src/core/request_controller.h
+++ b/src/core/request_controller.h
@@ -70,10 +70,7 @@ public:
}
}
- virtual ~RequestController()
- {
- reject();
- }
+ virtual ~RequestController() {}
protected:
virtual void accepted() = 0;
diff --git a/src/core/user_script.cpp b/src/core/user_script.cpp
index 9b9d66d55..bdd6524ca 100644
--- a/src/core/user_script.cpp
+++ b/src/core/user_script.cpp
@@ -38,7 +38,6 @@
****************************************************************************/
#include "common/user_script_data.h"
-#include "extensions/common/url_pattern.h"
#include "user_script.h"
#include "type_conversion.h"
@@ -66,11 +65,6 @@ bool GetDeclarationValue(const base::StringPiece& line,
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)
@@ -222,8 +216,6 @@ void UserScript::parseMetadataHeader()
// 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);
@@ -260,8 +252,7 @@ void UserScript::parseMetadataHeader()
}
scriptData->excludeGlobs.push_back(value);
} else if (GetDeclarationValue(line, kMatchDeclaration, &value)) {
- if (URLPattern::PARSE_SUCCESS == urlPatternParser.Parse(value))
- scriptData->urlPatterns.push_back(value);
+ scriptData->urlPatterns.push_back(value);
} else if (GetDeclarationValue(line, kRunAtDeclaration, &value)) {
if (value == kRunAtDocumentStartValue)
scriptData->injectionPoint = DocumentElementCreation;
diff --git a/src/core/user_script.h b/src/core/user_script.h
index e44efd3e9..93cde9aa6 100644
--- a/src/core/user_script.h
+++ b/src/core/user_script.h
@@ -85,8 +85,6 @@ public:
bool operator==(const UserScript &) const;
- static int validUserScriptSchemes();
-
private:
void initData();
UserScriptData &data() const;
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 4c5133772..0469867f2 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -449,6 +449,7 @@ public:
virtual void updateContentsSize(const QSizeF &size) = 0;
virtual void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions,
const QPixmap &pixmap, const QPoint &offset) = 0;
+ virtual bool supportsDragging() const = 0;
virtual bool isEnabled() const = 0;
virtual const QObject *holdingQObject() const = 0;
virtual void setToolTip(const QString& toolTipText) = 0;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 2de8fd64a..fe1f6fee0 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -44,6 +44,7 @@
#include "web_contents_delegate_qt.h"
#include "browser_context_adapter.h"
+#include "browser_context_qt.h"
#include "color_chooser_qt.h"
#include "color_chooser_controller.h"
#include "favicon_manager.h"
@@ -115,19 +116,25 @@ WebContentsDelegateQt::~WebContentsDelegateQt()
content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents *source, const content::OpenURLParams &params)
{
content::WebContents *target = source;
+ content::SiteInstance *target_site_instance = params.source_site_instance.get();
+ content::Referrer referrer = params.referrer;
if (params.disposition != WindowOpenDisposition::CURRENT_TAB) {
QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(0, params.disposition, gfx::Rect(), params.user_gesture);
if (targetAdapter) {
+ if (targetAdapter->browserContext() != source->GetBrowserContext()) {
+ target_site_instance = nullptr;
+ referrer = content::Referrer();
+ }
if (!targetAdapter->isInitialized())
- targetAdapter->initialize(params.source_site_instance.get());
+ targetAdapter->initialize(target_site_instance);
target = targetAdapter->webContents();
}
}
Q_ASSERT(target);
content::NavigationController::LoadURLParams load_url_params(params.url);
- load_url_params.source_site_instance = params.source_site_instance;
- load_url_params.referrer = params.referrer;
+ load_url_params.source_site_instance = target_site_instance;
+ load_url_params.referrer = referrer;
load_url_params.frame_tree_node_id = params.frame_tree_node_id;
load_url_params.redirect_chain = params.redirect_chain;
load_url_params.transition_type = params.transition;
@@ -519,6 +526,17 @@ void WebContentsDelegateQt::ActivateContents(content::WebContents* contents)
contents->Focus();
}
+void WebContentsDelegateQt::RenderViewHostChanged(content::RenderViewHost *old_host, content::RenderViewHost *new_host)
+{
+ Q_ASSERT(new_host);
+
+ // The old RVH can be nullptr if it was shut down.
+ if (!old_host)
+ return;
+
+ new_host->UpdateWebkitPreferences(old_host->GetWebkitPreferences());
+}
+
void WebContentsDelegateQt::RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target)
{
Q_UNUSED(user_gesture);
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index 2ef87ccd8..43badf60e 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -139,6 +139,7 @@ public:
void WasShown() override;
void DidFirstVisuallyNonEmptyPaint() override;
void ActivateContents(content::WebContents* contents) override;
+ void RenderViewHostChanged(content::RenderViewHost *old_host, content::RenderViewHost *new_host) override;
void didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription);
void overrideWebPreferences(content::WebContents *, content::WebPreferences*);
diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp
index a7895d61c..6b68a9569 100644
--- a/src/core/web_contents_view_qt.cpp
+++ b/src/core/web_contents_view_qt.cpp
@@ -232,6 +232,12 @@ void WebContentsViewQt::StartDragging(const content::DropData &drop_data,
#if QT_CONFIG(draganddrop)
Q_UNUSED(event_info);
+ if (!m_client->supportsDragging()) {
+ if (source_rwh)
+ source_rwh->DragSourceSystemDragEnded();
+ return;
+ }
+
QPixmap pixmap;
QPoint hotspot;
pixmap = QPixmap::fromImage(toQImage(image.GetRepresentation(m_client->dpiScale())));
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index fde7b40dc..babfbd014 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -1012,6 +1012,13 @@ void QQuickWebEngineViewPrivate::startDragging(const content::DropData &dropData
#endif // QT_CONFIG(draganddrop)
}
+bool QQuickWebEngineViewPrivate::supportsDragging() const
+{
+ // QTBUG-57516
+ // Fixme: This is just a band-aid workaround.
+ return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows);
+}
+
bool QQuickWebEngineViewPrivate::isEnabled() const
{
const Q_Q(QQuickWebEngineView);
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 73607aa59..1723da7ea 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -144,6 +144,7 @@ public:
void updateContentsSize(const QSizeF &size) override;
void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions,
const QPixmap &pixmap, const QPoint &offset) override;
+ bool supportsDragging() const override;
bool isEnabled() const override;
void setToolTip(const QString &toolTipText) override;
const QObject *holdingQObject() const override;
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 8911c63c8..ae47ee39f 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -47,7 +47,6 @@
#include "favicon_manager.h"
#include "file_picker_controller.h"
#include "javascript_dialog_controller.h"
-#include "printing/pdfium_document_wrapper_qt.h"
#include "qwebenginefullscreenrequest.h"
#include "qwebenginehistory.h"
#include "qwebenginehistory_p.h"
@@ -87,6 +86,10 @@
#include <QTimer>
#include <QUrl>
+#if defined(ENABLE_PRINTING) && defined(ENABLE_PDF)
+#include "printing/pdfium_document_wrapper_qt.h"
+#endif
+
QT_BEGIN_NAMESPACE
using namespace QtWebEngineCore;
@@ -1673,6 +1676,11 @@ void QWebEnginePagePrivate::startDragging(const content::DropData &dropData,
#endif // QT_CONFIG(draganddrop)
}
+bool QWebEnginePagePrivate::supportsDragging() const
+{
+ return true;
+}
+
bool QWebEnginePagePrivate::isEnabled() const
{
const Q_Q(QWebEnginePage);
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index dc7d02b73..fde877255 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -142,6 +142,7 @@ public:
void updateContentsSize(const QSizeF &size) override;
void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions,
const QPixmap &pixmap, const QPoint &offset) override;
+ bool supportsDragging() const override;
bool isEnabled() const override;
void setToolTip(const QString &toolTipText) override;
const QObject *holdingQObject() const override;
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 80c60e1a8..f03679d17 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -259,7 +259,8 @@ void QWebEngineView::findText(const QString &subString, QWebEnginePage::FindFlag
*/
QSize QWebEngineView::sizeHint() const
{
- return QSize(800, 600);
+ // TODO: Remove this override for Qt 6
+ return QWidget::sizeHint();
}
QWebEngineSettings *QWebEngineView::settings() const
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 16ea216f2..98482ae78 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -198,6 +198,9 @@ void RenderWidgetHostViewQtDelegateWidget::initAsChild(WebContentsAdapterClient*
disconnect(parentWidget(), &QObject::destroyed,
this, &RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete);
pagePrivate->view->layout()->addWidget(this);
+ if (QWidget *focusProxy = pagePrivate->view->focusProxy())
+ if (focusProxy != this)
+ pagePrivate->view->layout()->removeWidget(focusProxy);
pagePrivate->view->setFocusProxy(this);
show();
} else
@@ -250,6 +253,7 @@ void RenderWidgetHostViewQtDelegateWidget::setKeyboardFocus()
QGuiApplication::sync();
m_rootItem->forceActiveFocus();
+ setFocus();
}
bool RenderWidgetHostViewQtDelegateWidget::hasKeyboardFocus()
diff --git a/tests/auto/quick/qmltests/data/script-with-bad-match-metadata.js b/tests/auto/quick/qmltests/data/script-with-bad-match-metadata.js
new file mode 100644
index 000000000..c9a811e5c
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/script-with-bad-match-metadata.js
@@ -0,0 +1,9 @@
+// ==UserScript==
+// @name Test bad match script
+// @homepageURL http://www.qt.io/
+// @description Test script with metadata block with an invalid match directive
+// @match some:junk
+// @run-at document-end
+// ==/UserScript==
+
+document.title = "New title for some:junk";
diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml
index d7c7d5983..f4fcc30ab 100644
--- a/tests/auto/quick/qmltests/data/tst_userScripts.qml
+++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml
@@ -54,6 +54,11 @@ Item {
sourceUrl: Qt.resolvedUrl("script-with-metadata.js")
}
+ WebEngineScript {
+ id: scriptWithBadMatchMetadata
+ sourceUrl: Qt.resolvedUrl("script-with-bad-match-metadata.js")
+ }
+
TestWebEngineView {
id: webEngineView
width: 400
@@ -191,6 +196,18 @@ Item {
tryCompare(webEngineView, "title", "Test page with huge link area and iframe");
}
+ function test_dontInjectBadUrlPatternsEverywhere() {
+ compare(scriptWithBadMatchMetadata.name, "Test bad match script");
+ compare(scriptWithBadMatchMetadata.injectionPoint, WebEngineScript.DocumentReady);
+
+ webEngineView.userScripts = [ scriptWithBadMatchMetadata ];
+
+ // @match some:junk
+ webEngineView.url = Qt.resolvedUrl("test2.html");
+ webEngineView.waitForLoadSucceeded();
+ tryCompare(webEngineView, "title", "Test page with huge link area");
+ }
+
function test_profileWideScript() {
webEngineView.profile.userScripts = [ changeDocumentTitleScript ];
diff --git a/tests/auto/widgets/origins/resources/dedicatedWorker.html b/tests/auto/widgets/origins/resources/dedicatedWorker.html
new file mode 100644
index 000000000..cb4f14e73
--- /dev/null
+++ b/tests/auto/widgets/origins/resources/dedicatedWorker.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>dedicatedWorker</title>
+ <script>
+ var done = false;
+ var result;
+ var error;
+ try {
+ let worker = new Worker("dedicatedWorker.js");
+ worker.onmessage = (e) => { done = true; result = e.data; };
+ worker.postMessage(41);
+ } catch (e) {
+ done = true; error = e.message;
+ }
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/widgets/origins/resources/dedicatedWorker.js b/tests/auto/widgets/origins/resources/dedicatedWorker.js
new file mode 100644
index 000000000..2631939d7
--- /dev/null
+++ b/tests/auto/widgets/origins/resources/dedicatedWorker.js
@@ -0,0 +1 @@
+onmessage = (e) => { postMessage(e.data + 1); };
diff --git a/tests/auto/widgets/origins/resources/serviceWorker.html b/tests/auto/widgets/origins/resources/serviceWorker.html
new file mode 100644
index 000000000..b2bdc8c60
--- /dev/null
+++ b/tests/auto/widgets/origins/resources/serviceWorker.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>serviceWorker</title>
+ <script>
+ var done = false;
+ var error;
+ navigator.serviceWorker.register("serviceWorker.js")
+ .then((r) => { done = true; })
+ .catch((e) => { done = true; error = e.message; });
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/widgets/origins/resources/serviceWorker.js b/tests/auto/widgets/origins/resources/serviceWorker.js
new file mode 100644
index 000000000..40a8c178f
--- /dev/null
+++ b/tests/auto/widgets/origins/resources/serviceWorker.js
@@ -0,0 +1 @@
+/* empty */
diff --git a/tests/auto/widgets/origins/resources/sharedWorker.html b/tests/auto/widgets/origins/resources/sharedWorker.html
new file mode 100644
index 000000000..8b5a0a794
--- /dev/null
+++ b/tests/auto/widgets/origins/resources/sharedWorker.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>sharedWorker</title>
+ <script>
+ var done;
+ var result;
+ var error;
+ try {
+ let worker = new SharedWorker("sharedWorker.js");
+ worker.port.onmessage = (e) => { done = true; result = e.data; };
+ worker.port.postMessage(41);
+ } catch (e) {
+ done = true; error = e.message;
+ }
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/tests/auto/widgets/origins/resources/sharedWorker.js b/tests/auto/widgets/origins/resources/sharedWorker.js
new file mode 100644
index 000000000..60ef93a5f
--- /dev/null
+++ b/tests/auto/widgets/origins/resources/sharedWorker.js
@@ -0,0 +1,6 @@
+onconnect = function(e) {
+ let port = e.ports[0];
+ port.onmessage = function(e) {
+ port.postMessage(e.data + 1);
+ };
+};
diff --git a/tests/auto/widgets/origins/tst_origins.cpp b/tests/auto/widgets/origins/tst_origins.cpp
index 5c798ddc2..61d54e6de 100644
--- a/tests/auto/widgets/origins/tst_origins.cpp
+++ b/tests/auto/widgets/origins/tst_origins.cpp
@@ -73,6 +73,9 @@ private Q_SLOTS:
void subdirWithoutAccess();
void mixedSchemes();
void webSocket();
+ void dedicatedWorker();
+ void sharedWorker();
+ void serviceWorker();
private:
bool load(const QUrl &url)
@@ -259,9 +262,74 @@ void tst_Origins::webSocket()
QVERIFY(load(QSL("qrc:/resources/websocket.html")));
QTRY_VERIFY(eval(QSL("err")) == QVariant(expected));
+ QVERIFY(load(QSL("tst:/resources/websocket.html")));
+ QTRY_VERIFY(eval(QSL("err")) == QVariant(expected));
+}
+
+// Create a (Dedicated)Worker. Since dedicated workers can only be accessed from
+// one page, there is not much need for security restrictions.
+void tst_Origins::dedicatedWorker()
+{
+ QVERIFY(load(QSL("file:" THIS_DIR "resources/dedicatedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
+ QVERIFY(load(QSL("qrc:/resources/dedicatedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
// FIXME(juvaldma): QTBUG-62536
- // QVERIFY(load(QSL("tst:/resources/websocket.html")));
- // QTRY_VERIFY(eval(QSL("err")) == QVariant(expected));
+ QVERIFY(load(QSL("tst:/resources/dedicatedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("Access to dedicated workers is denied to origin 'tst://'")));
+}
+
+// Create a SharedWorker. Shared workers can be accessed from multiple pages,
+// and therefore the same-origin policy applies.
+void tst_Origins::sharedWorker()
+{
+ {
+ ScopedAttribute sa(m_page.settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, false);
+ QVERIFY(load(QSL("file:" THIS_DIR "resources/sharedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("cannot be accessed from origin 'null'")));
+ }
+
+ {
+ ScopedAttribute sa(m_page.settings(), QWebEngineSettings::LocalContentCanAccessFileUrls, true);
+ QVERIFY(load(QSL("file:" THIS_DIR "resources/sharedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+ }
+
+ QVERIFY(load(QSL("qrc:/resources/sharedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+
+ QVERIFY(load(QSL("tst:/resources/sharedWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QCOMPARE(eval(QSL("result")), QVariant(42));
+}
+
+// Service workers don't work.
+void tst_Origins::serviceWorker()
+{
+ QVERIFY(load(QSL("file:" THIS_DIR "resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("The URL protocol of the current origin ('file://') is not supported.")));
+
+ QVERIFY(load(QSL("qrc:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("The URL protocol of the current origin ('qrc://') is not supported.")));
+
+ QVERIFY(load(QSL("tst:/resources/serviceWorker.html")));
+ QTRY_VERIFY(eval(QSL("done")).toBool());
+ QVERIFY(eval(QSL("error")).toString()
+ .contains(QSL("Only secure origins are allowed")));
}
QTEST_MAIN(tst_Origins)
diff --git a/tests/auto/widgets/origins/tst_origins.qrc b/tests/auto/widgets/origins/tst_origins.qrc
index 47be3bd0d..fbbbef139 100644
--- a/tests/auto/widgets/origins/tst_origins.qrc
+++ b/tests/auto/widgets/origins/tst_origins.qrc
@@ -1,9 +1,15 @@
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource>
+ <file>resources/dedicatedWorker.html</file>
+ <file>resources/dedicatedWorker.js</file>
<file>resources/mixed_frame.html</file>
<file>resources/mixed_qrc.html</file>
<file>resources/mixed_tst.html</file>
+ <file>resources/serviceWorker.html</file>
+ <file>resources/serviceWorker.js</file>
+ <file>resources/sharedWorker.html</file>
+ <file>resources/sharedWorker.js</file>
<file>resources/subdir/frame2.html</file>
<file>resources/subdir/index.html</file>
<file>resources/subdir_frame1.html</file>
diff --git a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp
index 4848038df..f932d50c3 100644
--- a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp
+++ b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp
@@ -112,6 +112,7 @@ void tst_QWebEngineDownloads::initTestCase()
m_page = new QWebEnginePage(m_profile);
m_view = new QWebEngineView;
m_view->setPage(m_page);
+ m_view->resize(640, 480);
m_view->show();
}
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index d62ace045..8d0d5c43c 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -217,6 +217,7 @@ private Q_SLOTS:
void registerProtocolHandler();
void dataURLFragment();
void devTools();
+ void openLinkInDifferentProfile();
private:
static QPoint elementCenter(QWebEnginePage *page, const QString &id);
@@ -3312,6 +3313,7 @@ protected:
void tst_QWebEnginePage::evaluateWillCauseRepaint()
{
WebView view;
+ view.resize(640, 480);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
@@ -4052,6 +4054,7 @@ void tst_QWebEnginePage::mouseButtonTranslation()
<div style=\"height:600px;\" onmousedown=\"saveLastEvent(event)\">\
</div>\
</body></html>"));
+ view.resize(640, 480);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
QTRY_VERIFY(spy.count() == 1);
@@ -4076,6 +4079,7 @@ void tst_QWebEnginePage::mouseMovementProperties()
QWebEngineView view;
ConsolePage page;
view.setPage(&page);
+ view.resize(640, 480);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
@@ -4370,6 +4374,34 @@ void tst_QWebEnginePage::devTools()
QCOMPARE(devToolsPage.inspectedPage(), nullptr);
}
+void tst_QWebEnginePage::openLinkInDifferentProfile()
+{
+ class Page : public QWebEnginePage {
+ public:
+ QWebEnginePage *targetPage = nullptr;
+ Page(QWebEngineProfile *profile) : QWebEnginePage(profile) {}
+ private:
+ QWebEnginePage *createWindow(WebWindowType) override { return targetPage; }
+ };
+ QWebEngineProfile profile1, profile2;
+ Page page1(&profile1), page2(&profile2);
+ QWebEngineView view;
+ view.resize(500, 500);
+ view.setPage(&page1);
+ view.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QSignalSpy spy1(&page1, &QWebEnginePage::loadFinished), spy2(&page2, &QWebEnginePage::loadFinished);
+ page1.setHtml("<html><body>"
+ "<a id='link' href='data:,hello'>link</a>"
+ "</body></html>");
+ QTRY_COMPARE(spy1.count(), 1);
+ QVERIFY(spy1.takeFirst().value(0).toBool());
+ page1.targetPage = &page2;
+ QTest::mouseClick(view.focusProxy(), Qt::MiddleButton, 0, elementCenter(&page1, "link"));
+ QTRY_COMPARE(spy2.count(), 1);
+ QVERIFY(spy2.takeFirst().value(0).toBool());
+}
+
static QByteArrayList params = {QByteArrayLiteral("--use-fake-device-for-media-stream")};
W_QTEST_MAIN(tst_QWebEnginePage, params)
diff --git a/tests/auto/widgets/qwebenginescript/resources/webChannelWithBadString.html b/tests/auto/widgets/qwebenginescript/resources/webChannelWithBadString.html
new file mode 100644
index 000000000..ca2bc0f27
--- /dev/null
+++ b/tests/auto/widgets/qwebenginescript/resources/webChannelWithBadString.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>webChannelWithBadString</title>
+ </head>
+ <body>
+ <script src="qrc:/qtwebchannel/qwebchannel.js"></script>
+ <script type="text/javascript">
+ new QWebChannel(qt.webChannelTransport, (channel) => {
+ channel.objects.host.text = String.fromCharCode(0xD800);
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
index cb45e524e..23d31a478 100644
--- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
+++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
@@ -42,6 +42,7 @@ private Q_SLOTS:
void webChannelResettingAndUnsetting();
void webChannelWithExistingQtObject();
void navigation();
+ void webChannelWithBadString();
};
void tst_QWebEngineScript::domEditing()
@@ -263,9 +264,8 @@ static QString readFile(const QString &path)
static QWebEngineScript webChannelScript()
{
- QString sourceCode = readFile(QStringLiteral(":/qwebchannel.js"));
- if (sourceCode.isEmpty())
- return {};
+ QString sourceCode = readFile(QStringLiteral(":/qtwebchannel/qwebchannel.js"));
+ Q_ASSERT(!sourceCode.isEmpty());
QWebEngineScript script;
script.setSourceCode(sourceCode);
@@ -470,6 +470,22 @@ void tst_QWebEngineScript::navigation()
QCOMPARE(testObject.text(), url3);
}
+// Try to set TestObject::text to an invalid UTF-16 string.
+//
+// See QTBUG-61969.
+void tst_QWebEngineScript::webChannelWithBadString()
+{
+ QWebEnginePage page;
+ TestObject host;
+ QSignalSpy hostSpy(&host, &TestObject::textChanged);
+ QWebChannel channel;
+ channel.registerObject(QStringLiteral("host"), &host);
+ page.setWebChannel(&channel);
+ page.setUrl(QStringLiteral("qrc:/resources/webChannelWithBadString.html"));
+ QVERIFY(hostSpy.wait(20000));
+ QCOMPARE(host.text(), QString(QChar(QChar::ReplacementCharacter)));
+}
+
QTEST_MAIN(tst_QWebEngineScript)
#include "tst_qwebenginescript.moc"
diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc
index 9960a37ba..ada06119a 100644
--- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc
+++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.qrc
@@ -4,5 +4,6 @@
<file>resources/test_iframe_outer.html</file>
<file>resources/test_iframe_inner.html</file>
<file>resources/test_window_open.html</file>
+ <file>resources/webChannelWithBadString.html</file>
</qresource>
</RCC>
diff --git a/tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp b/tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp
index 845520628..150b3c554 100644
--- a/tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp
+++ b/tests/auto/widgets/qwebenginesettings/tst_qwebenginesettings.cpp
@@ -37,6 +37,7 @@ private Q_SLOTS:
void defaultFontFamily();
void javascriptClipboard_data();
void javascriptClipboard();
+ void setInAcceptNavigationRequest();
};
void tst_QWebEngineSettings::resetAttributes()
@@ -162,6 +163,40 @@ void tst_QWebEngineSettings::javascriptClipboard()
(pasteResult ? QString("AnotherText") : QString("OriginalText")));
}
+class NavigationRequestOverride : public QWebEnginePage
+{
+protected:
+ virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame)
+ {
+ Q_UNUSED(type);
+
+ if (isMainFrame && url.scheme().startsWith("data"))
+ settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
+
+ return true;
+ }
+};
+
+void tst_QWebEngineSettings::setInAcceptNavigationRequest()
+{
+ NavigationRequestOverride page;
+ QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+ QWebEngineSettings::globalSettings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false);
+ QVERIFY(!page.settings()->testAttribute(QWebEngineSettings::JavascriptEnabled));
+
+ page.load(QUrl("about:blank"));
+ QVERIFY(loadFinishedSpy.wait());
+ QVERIFY(!page.settings()->testAttribute(QWebEngineSettings::JavascriptEnabled));
+
+ page.setHtml("<html><body>"
+ "<script>document.write('PASS')</script>"
+ "<noscript>FAIL</noscript>"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+ QVERIFY(page.settings()->testAttribute(QWebEngineSettings::JavascriptEnabled));
+ QCOMPARE(toPlainTextSync(&page), QStringLiteral("PASS"));
+}
+
QTEST_MAIN(tst_QWebEngineSettings)
#include "tst_qwebenginesettings.moc"
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index 207836bef..248d906ef 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -153,6 +153,7 @@ private Q_SLOTS:
void focusOnNavigation_data();
void focusOnNavigation();
void focusInternalRenderWidgetHostViewQuickItem();
+ void doNotBreakLayout();
void changeLocale();
void inputMethodsTextFormat_data();
@@ -173,6 +174,7 @@ private Q_SLOTS:
void imeCompositionQueryEvent_data();
void imeCompositionQueryEvent();
void newlineInTextarea();
+ void imeJSInputEvents();
void mouseLeave();
@@ -344,6 +346,7 @@ void tst_QWebEngineView::crashTests()
void tst_QWebEngineView::microFocusCoordinates()
{
QWebEngineView webView;
+ webView.resize(640, 480);
webView.show();
QVERIFY(QTest::qWaitForWindowExposed(&webView));
@@ -378,6 +381,7 @@ void tst_QWebEngineView::focusInputTypes()
bool imeHasHiddenTextCapability = context && context->hasCapability(QPlatformInputContext::HiddenTextCapability);
QWebEngineView webView;
+ webView.resize(640, 480);
webView.show();
QVERIFY(QTest::qWaitForWindowExposed(&webView));
@@ -481,6 +485,7 @@ void tst_QWebEngineView::unhandledKeyEventPropagation()
{
KeyEventRecordingWidget parentWidget;
QWebEngineView webView(&parentWidget);
+ webView.resize(640, 480);
parentWidget.show();
QVERIFY(QTest::qWaitForWindowExposed(&webView));
@@ -824,6 +829,7 @@ void tst_QWebEngineView::doNotSendMouseKeyboardEventsWhenDisabled()
QFETCH(int, resultEventCount);
KeyboardAndMouseEventRecordingWidget parentWidget;
+ parentWidget.resize(640, 480);
QWebEngineView webView(&parentWidget);
webView.setEnabled(viewEnabled);
parentWidget.setLayout(new QStackedLayout);
@@ -1029,6 +1035,31 @@ void tst_QWebEngineView::focusInternalRenderWidgetHostViewQuickItem()
QTRY_COMPARE(renderWidgetHostViewQuickItem->hasFocus(), true);
}
+void tst_QWebEngineView::doNotBreakLayout()
+{
+ QScopedPointer<QWidget> containerWidget(new QWidget);
+
+ QHBoxLayout *layout = new QHBoxLayout;
+ layout->addWidget(new QWidget);
+ layout->addWidget(new QWidget);
+ layout->addWidget(new QWidget);
+ layout->addWidget(new QWebEngineView);
+
+ containerWidget->setLayout(layout);
+ containerWidget->setGeometry(50, 50, 800, 600);
+ containerWidget->show();
+ QVERIFY(QTest::qWaitForWindowExposed(containerWidget.data()));
+
+ QSize previousSize = static_cast<QWidgetItem *>(layout->itemAt(0))->widget()->size();
+ for (int i = 1; i < layout->count(); i++) {
+ QSize actualSize = static_cast<QWidgetItem *>(layout->itemAt(i))->widget()->size();
+ // There could be smaller differences on some platforms
+ QVERIFY(qAbs(previousSize.width() - actualSize.width()) <= 2);
+ QVERIFY(qAbs(previousSize.height() - actualSize.height()) <= 2);
+ previousSize = actualSize;
+ }
+}
+
void tst_QWebEngineView::changeLocale()
{
QStringList errorLines;
@@ -1592,6 +1623,7 @@ void tst_QWebEngineView::softwareInputPanel()
{
TestInputContext testContext;
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
@@ -1648,6 +1680,7 @@ void tst_QWebEngineView::softwareInputPanel()
void tst_QWebEngineView::inputMethods()
{
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
@@ -1744,6 +1777,7 @@ void tst_QWebEngineView::inputMethods()
void tst_QWebEngineView::textSelectionInInputField()
{
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
@@ -1825,6 +1859,7 @@ void tst_QWebEngineView::textSelectionInInputField()
void tst_QWebEngineView::textSelectionOutOfInputField()
{
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
@@ -1908,6 +1943,7 @@ void tst_QWebEngineView::textSelectionOutOfInputField()
void tst_QWebEngineView::hiddenText()
{
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
@@ -1933,6 +1969,7 @@ void tst_QWebEngineView::hiddenText()
void tst_QWebEngineView::emptyInputMethodEvent()
{
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
@@ -1979,6 +2016,7 @@ void tst_QWebEngineView::emptyInputMethodEvent()
void tst_QWebEngineView::imeComposition()
{
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
@@ -2153,6 +2191,7 @@ void tst_QWebEngineView::imeComposition()
void tst_QWebEngineView::newlineInTextarea()
{
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
@@ -2249,6 +2288,142 @@ void tst_QWebEngineView::newlineInTextarea()
QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("\n\nthird line"));
}
+void tst_QWebEngineView::imeJSInputEvents()
+{
+ QWebEngineView view;
+ view.resize(640, 480);
+ view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
+ view.show();
+
+ auto logLines = [&view]() -> QStringList {
+ return evaluateJavaScriptSync(view.page(), "log.textContent").toString().split("\n").filter(QRegExp(".+"));
+ };
+
+ QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+ view.page()->setHtml("<html>"
+ "<head><script>"
+ " var input, log;"
+ " function verboseEvent(ev) {"
+ " log.textContent += ev + ' ' + ev.type + ' ' + ev.data + '\\n';"
+ " }"
+ " function clear(ev) {"
+ " log.textContent = '';"
+ " input.textContent = '';"
+ " }"
+ " function init() {"
+ " input = document.getElementById('input');"
+ " log = document.getElementById('log');"
+ " events = [ 'textInput', 'beforeinput', 'input', 'compositionstart', 'compositionupdate', 'compositionend' ];"
+ " for (var e in events)"
+ " input.addEventListener(events[e], verboseEvent);"
+ " }"
+ "</script></head>"
+ "<body onload='init()'>"
+ " <div id='input' contenteditable='true' style='border-style: solid;'></div>"
+ " <pre id='log'></pre>"
+ "</body></html>");
+ QVERIFY(loadFinishedSpy.wait());
+
+ evaluateJavaScriptSync(view.page(), "document.getElementById('input').focus()");
+ QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input"));
+
+ // 1. Commit text (this is how dead keys work on Linux).
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString("commit");
+ QApplication::sendEvent(view.focusProxy(), &event);
+ qApp->processEvents();
+ }
+
+ // Simply committing text should not trigger any JS composition event.
+ QTRY_COMPARE(logLines().count(), 3);
+ QCOMPARE(logLines()[0], "[object InputEvent] beforeinput commit");
+ QCOMPARE(logLines()[1], "[object TextEvent] textInput commit");
+ QCOMPARE(logLines()[2], "[object InputEvent] input commit");
+
+ evaluateJavaScriptSync(view.page(), "clear()");
+ QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "log.textContent + input.textContent").toString().isEmpty());
+
+ // 2. Start composition then commit text (this is how dead keys work on macOS).
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("preedit", attributes);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ qApp->processEvents();
+ }
+
+ QTRY_COMPARE(logLines().count(), 4);
+ QCOMPARE(logLines()[0], "[object CompositionEvent] compositionstart ");
+ QCOMPARE(logLines()[1], "[object InputEvent] beforeinput preedit");
+ QCOMPARE(logLines()[2], "[object CompositionEvent] compositionupdate preedit");
+ QCOMPARE(logLines()[3], "[object InputEvent] input preedit");
+
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString("commit");
+ QApplication::sendEvent(view.focusProxy(), &event);
+ qApp->processEvents();
+ }
+
+ QTRY_COMPARE(logLines().count(), 9);
+ QCOMPARE(logLines()[4], "[object InputEvent] beforeinput commit");
+ QCOMPARE(logLines()[5], "[object CompositionEvent] compositionupdate commit");
+ QCOMPARE(logLines()[6], "[object TextEvent] textInput commit");
+ QCOMPARE(logLines()[7], "[object InputEvent] input commit");
+ QCOMPARE(logLines()[8], "[object CompositionEvent] compositionend commit");
+
+ evaluateJavaScriptSync(view.page(), "clear()");
+ QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "log.textContent + input.textContent").toString().isEmpty());
+
+ // 3. Start composition then cancel it with an empty IME event.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("preedit", attributes);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ qApp->processEvents();
+ }
+
+ QTRY_COMPARE(logLines().count(), 4);
+ QCOMPARE(logLines()[0], "[object CompositionEvent] compositionstart ");
+ QCOMPARE(logLines()[1], "[object InputEvent] beforeinput preedit");
+ QCOMPARE(logLines()[2], "[object CompositionEvent] compositionupdate preedit");
+ QCOMPARE(logLines()[3], "[object InputEvent] input preedit");
+
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ qApp->processEvents();
+ }
+
+ QTRY_COMPARE(logLines().count(), 9);
+ QCOMPARE(logLines()[4], "[object InputEvent] beforeinput ");
+ QCOMPARE(logLines()[5], "[object CompositionEvent] compositionupdate ");
+ QCOMPARE(logLines()[6], "[object TextEvent] textInput ");
+ QCOMPARE(logLines()[7], "[object InputEvent] input null");
+ QCOMPARE(logLines()[8], "[object CompositionEvent] compositionend ");
+
+ evaluateJavaScriptSync(view.page(), "clear()");
+ QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "log.textContent + input.textContent").toString().isEmpty());
+
+ // 4. Send empty IME event.
+ {
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ QApplication::sendEvent(view.focusProxy(), &event);
+ qApp->processEvents();
+ }
+
+ // No JS event is expected.
+ QTest::qWait(100);
+ QVERIFY(logLines().isEmpty());
+
+ evaluateJavaScriptSync(view.page(), "clear()");
+ QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "log.textContent + input.textContent").toString().isEmpty());
+}
+
void tst_QWebEngineView::imeCompositionQueryEvent_data()
{
QTest::addColumn<QString>("receiverObjectName");
@@ -2260,6 +2435,7 @@ void tst_QWebEngineView::imeCompositionQueryEvent_data()
void tst_QWebEngineView::imeCompositionQueryEvent()
{
QWebEngineView view;
+ view.resize(640, 480);
view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
view.show();
@@ -2341,6 +2517,7 @@ void tst_QWebEngineView::globalMouseSelection()
QApplication::clipboard()->clear(QClipboard::Selection);
QWebEngineView view;
+ view.resize(640, 480);
view.show();
QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
@@ -2421,6 +2598,7 @@ void tst_QWebEngineView::contextMenu()
}
view.setContextMenuPolicy(contextMenuPolicy);
+ view.resize(640, 480);
view.show();
QVERIFY(view.findChildren<QMenu *>().isEmpty());
diff --git a/tests/auto/widgets/resources/qwebchannel.js b/tests/auto/widgets/resources/qwebchannel.js
deleted file mode 100644
index 1da8f5496..000000000
--- a/tests/auto/widgets/resources/qwebchannel.js
+++ /dev/null
@@ -1,408 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2014 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebChannel 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$
-**
-****************************************************************************/
-
-"use strict";
-
-var QWebChannelMessageTypes = {
- signal: 1,
- propertyUpdate: 2,
- init: 3,
- idle: 4,
- debug: 5,
- invokeMethod: 6,
- connectToSignal: 7,
- disconnectFromSignal: 8,
- setProperty: 9,
- response: 10,
-};
-
-var QWebChannel = function(transport, initCallback)
-{
- if (typeof transport !== "object" || typeof transport.send !== "function") {
- console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." +
- " Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send));
- return;
- }
-
- var channel = this;
- this.transport = transport;
-
- this.send = function(data)
- {
- if (typeof(data) !== "string") {
- data = JSON.stringify(data);
- }
- channel.transport.send(data);
- }
-
- this.transport.onmessage = function(message)
- {
- var data = message.data;
- if (typeof data === "string") {
- data = JSON.parse(data);
- }
- switch (data.type) {
- case QWebChannelMessageTypes.signal:
- channel.handleSignal(data);
- break;
- case QWebChannelMessageTypes.response:
- channel.handleResponse(data);
- break;
- case QWebChannelMessageTypes.propertyUpdate:
- channel.handlePropertyUpdate(data);
- break;
- default:
- console.error("invalid message received:", message.data);
- break;
- }
- }
-
- this.execCallbacks = {};
- this.execId = 0;
- this.exec = function(data, callback)
- {
- if (!callback) {
- // if no callback is given, send directly
- channel.send(data);
- return;
- }
- if (channel.execId === Number.MAX_VALUE) {
- // wrap
- channel.execId = Number.MIN_VALUE;
- }
- if (data.hasOwnProperty("id")) {
- console.error("Cannot exec message with property id: " + JSON.stringify(data));
- return;
- }
- data.id = channel.execId++;
- channel.execCallbacks[data.id] = callback;
- channel.send(data);
- };
-
- this.objects = {};
-
- this.handleSignal = function(message)
- {
- var object = channel.objects[message.object];
- if (object) {
- object.signalEmitted(message.signal, message.args);
- } else {
- console.warn("Unhandled signal: " + message.object + "::" + message.signal);
- }
- }
-
- this.handleResponse = function(message)
- {
- if (!message.hasOwnProperty("id")) {
- console.error("Invalid response message received: ", JSON.stringify(message));
- return;
- }
- channel.execCallbacks[message.id](message.data);
- delete channel.execCallbacks[message.id];
- }
-
- this.handlePropertyUpdate = function(message)
- {
- for (var i in message.data) {
- var data = message.data[i];
- var object = channel.objects[data.object];
- if (object) {
- object.propertyUpdate(data.signals, data.properties);
- } else {
- console.warn("Unhandled property update: " + data.object + "::" + data.signal);
- }
- }
- channel.exec({type: QWebChannelMessageTypes.idle});
- }
-
- this.debug = function(message)
- {
- channel.send({type: QWebChannelMessageTypes.debug, data: message});
- };
-
- channel.exec({type: QWebChannelMessageTypes.init}, function(data) {
- for (var objectName in data) {
- var object = new QObject(objectName, data[objectName], channel);
- }
- // now unwrap properties, which might reference other registered objects
- for (var objectName in channel.objects) {
- channel.objects[objectName].unwrapProperties();
- }
- if (initCallback) {
- initCallback(channel);
- }
- channel.exec({type: QWebChannelMessageTypes.idle});
- });
-};
-
-function QObject(name, data, webChannel)
-{
- this.__id__ = name;
- webChannel.objects[name] = this;
-
- // List of callbacks that get invoked upon signal emission
- this.__objectSignals__ = {};
-
- // Cache of all properties, updated when a notify signal is emitted
- this.__propertyCache__ = {};
-
- var object = this;
-
- // ----------------------------------------------------------------------
-
- this.unwrapQObject = function(response)
- {
- if (response instanceof Array) {
- // support list of objects
- var ret = new Array(response.length);
- for (var i = 0; i < response.length; ++i) {
- ret[i] = object.unwrapQObject(response[i]);
- }
- return ret;
- }
- if (!response
- || !response["__QObject*__"]
- || response.id === undefined) {
- return response;
- }
-
- var objectId = response.id;
- if (webChannel.objects[objectId])
- return webChannel.objects[objectId];
-
- if (!response.data) {
- console.error("Cannot unwrap unknown QObject " + objectId + " without data.");
- return;
- }
-
- var qObject = new QObject( objectId, response.data, webChannel );
- qObject.destroyed.connect(function() {
- if (webChannel.objects[objectId] === qObject) {
- delete webChannel.objects[objectId];
- // reset the now deleted QObject to an empty {} object
- // just assigning {} though would not have the desired effect, but the
- // below also ensures all external references will see the empty map
- // NOTE: this detour is necessary to workaround QTBUG-40021
- var propertyNames = [];
- for (var propertyName in qObject) {
- propertyNames.push(propertyName);
- }
- for (var idx in propertyNames) {
- delete qObject[propertyNames[idx]];
- }
- }
- });
- // here we are already initialized, and thus must directly unwrap the properties
- qObject.unwrapProperties();
- return qObject;
- }
-
- this.unwrapProperties = function()
- {
- for (var propertyIdx in object.__propertyCache__) {
- object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]);
- }
- }
-
- function addSignal(signalData, isPropertyNotifySignal)
- {
- var signalName = signalData[0];
- var signalIndex = signalData[1];
- object[signalName] = {
- connect: function(callback) {
- if (typeof(callback) !== "function") {
- console.error("Bad callback given to connect to signal " + signalName);
- return;
- }
-
- object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
- object.__objectSignals__[signalIndex].push(callback);
-
- if (!isPropertyNotifySignal && signalName !== "destroyed") {
- // only required for "pure" signals, handled separately for properties in propertyUpdate
- // also note that we always get notified about the destroyed signal
- webChannel.exec({
- type: QWebChannelMessageTypes.connectToSignal,
- object: object.__id__,
- signal: signalIndex
- });
- }
- },
- disconnect: function(callback) {
- if (typeof(callback) !== "function") {
- console.error("Bad callback given to disconnect from signal " + signalName);
- return;
- }
- object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || [];
- var idx = object.__objectSignals__[signalIndex].indexOf(callback);
- if (idx === -1) {
- console.error("Cannot find connection of signal " + signalName + " to " + callback.name);
- return;
- }
- object.__objectSignals__[signalIndex].splice(idx, 1);
- if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === 0) {
- // only required for "pure" signals, handled separately for properties in propertyUpdate
- webChannel.exec({
- type: QWebChannelMessageTypes.disconnectFromSignal,
- object: object.__id__,
- signal: signalIndex
- });
- }
- }
- };
- }
-
- /**
- * Invokes all callbacks for the given signalname. Also works for property notify callbacks.
- */
- function invokeSignalCallbacks(signalName, signalArgs)
- {
- var connections = object.__objectSignals__[signalName];
- if (connections) {
- connections.forEach(function(callback) {
- callback.apply(callback, signalArgs);
- });
- }
- }
-
- this.propertyUpdate = function(signals, propertyMap)
- {
- // update property cache
- for (var propertyIndex in propertyMap) {
- var propertyValue = propertyMap[propertyIndex];
- object.__propertyCache__[propertyIndex] = propertyValue;
- }
-
- for (var signalName in signals) {
- // Invoke all callbacks, as signalEmitted() does not. This ensures the
- // property cache is updated before the callbacks are invoked.
- invokeSignalCallbacks(signalName, signals[signalName]);
- }
- }
-
- this.signalEmitted = function(signalName, signalArgs)
- {
- invokeSignalCallbacks(signalName, signalArgs);
- }
-
- function addMethod(methodData)
- {
- var methodName = methodData[0];
- var methodIdx = methodData[1];
- object[methodName] = function() {
- var args = [];
- var callback;
- for (var i = 0; i < arguments.length; ++i) {
- if (typeof arguments[i] === "function")
- callback = arguments[i];
- else
- args.push(arguments[i]);
- }
-
- webChannel.exec({
- "type": QWebChannelMessageTypes.invokeMethod,
- "object": object.__id__,
- "method": methodIdx,
- "args": args
- }, function(response) {
- if (response !== undefined) {
- var result = object.unwrapQObject(response);
- if (callback) {
- (callback)(result);
- }
- }
- });
- };
- }
-
- function bindGetterSetter(propertyInfo)
- {
- var propertyIndex = propertyInfo[0];
- var propertyName = propertyInfo[1];
- var notifySignalData = propertyInfo[2];
- // initialize property cache with current value
- // NOTE: if this is an object, it is not directly unwrapped as it might
- // reference other QObject that we do not know yet
- object.__propertyCache__[propertyIndex] = propertyInfo[3];
-
- if (notifySignalData) {
- if (notifySignalData[0] === 1) {
- // signal name is optimized away, reconstruct the actual name
- notifySignalData[0] = propertyName + "Changed";
- }
- addSignal(notifySignalData, true);
- }
-
- Object.defineProperty(object, propertyName, {
- configurable: true,
- get: function () {
- var propertyValue = object.__propertyCache__[propertyIndex];
- if (propertyValue === undefined) {
- // This shouldn't happen
- console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__);
- }
-
- return propertyValue;
- },
- set: function(value) {
- if (value === undefined) {
- console.warn("Property setter for " + propertyName + " called with undefined value!");
- return;
- }
- object.__propertyCache__[propertyIndex] = value;
- webChannel.exec({
- "type": QWebChannelMessageTypes.setProperty,
- "object": object.__id__,
- "property": propertyIndex,
- "value": value
- });
- }
- });
-
- }
-
- // ----------------------------------------------------------------------
-
- data.methods.forEach(addMethod);
-
- data.properties.forEach(bindGetterSetter);
-
- data.signals.forEach(function(signal) { addSignal(signal, false); });
-
- for (var name in data.enums) {
- object[name] = data.enums[name];
- }
-}
-
-//required for use with nodejs
-if (typeof module === 'object') {
- module.exports = {
- QWebChannel: QWebChannel
- };
-}
diff --git a/tests/auto/widgets/resources/tests.qrc b/tests/auto/widgets/resources/tests.qrc
deleted file mode 100644
index 5e9df2873..000000000
--- a/tests/auto/widgets/resources/tests.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/">
- <file>qwebchannel.js</file>
- </qresource>
-</RCC>
diff --git a/tests/auto/widgets/tests.pri b/tests/auto/widgets/tests.pri
index 7bd00834c..5e6699cf8 100644
--- a/tests/auto/widgets/tests.pri
+++ b/tests/auto/widgets/tests.pri
@@ -11,7 +11,6 @@ TARGET = tst_$$TARGET
SOURCES += $${TARGET}.cpp
INCLUDEPATH += $$PWD
-RESOURCES += ../resources/tests.qrc
exists($$_PRO_FILE_PWD_/$${TARGET}.qrc): RESOURCES += $${TARGET}.qrc
QT += testlib network webenginewidgets widgets quick quickwidgets