summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-15 16:14:58 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-15 16:14:58 +0100
commit14988cd6b243986f501edbba678796ea5efe2c28 (patch)
treec2555af8f13b5336047e17548092bf1590f81576
parentf17f815878d1d3f02f464347d2807555cab00a88 (diff)
parentc69f510ed6e85c64f02ee0ee030336cd9aa66793 (diff)
downloadqtwebengine-14988cd6b243986f501edbba678796ea5efe2c28.tar.gz
Merge branch '5.13' into dev
Change-Id: I06d0cb28448768f16c886b96fec1da4a1b82e1d7
-rw-r--r--dist/changes-5.12.178
-rw-r--r--examples/webenginewidgets/simplebrowser/browserwindow.cpp3
-rw-r--r--examples/webenginewidgets/simplebrowser/webpage.cpp2
m---------src/3rdparty0
-rw-r--r--src/core/api/core_api.pro3
-rw-r--r--src/core/api/qwebengineclientcertificatestore.cpp (renamed from src/core/qwebengineclientcertificatestore.cpp)161
-rw-r--r--src/core/api/qwebengineclientcertificatestore.h10
-rw-r--r--src/core/api/qwebenginenotification.cpp275
-rw-r--r--src/core/api/qwebenginenotification.h112
-rw-r--r--src/core/api/qwebengineurlrequestinfo.cpp10
-rw-r--r--src/core/api/qwebengineurlrequestinterceptor.h2
-rw-r--r--src/core/api/qwebengineurlscheme.cpp33
-rw-r--r--src/core/api/qwebengineurlscheme.h4
-rw-r--r--src/core/chromium_overrides.cpp30
-rw-r--r--src/core/command_line_pref_store_qt.cpp90
-rw-r--r--src/core/command_line_pref_store_qt.h (renamed from src/core/chromium_overrides.h)26
-rw-r--r--src/core/compositor/compositor_resource.h3
-rw-r--r--src/core/compositor/delegated_frame_node.cpp2
-rw-r--r--src/core/config/linux.pri9
-rw-r--r--src/core/content_browser_client_qt.cpp29
-rw-r--r--src/core/content_browser_client_qt.h3
-rw-r--r--src/core/content_client_qt.cpp14
-rw-r--r--src/core/core_chromium.pri17
-rw-r--r--src/core/core_common.pri4
-rw-r--r--src/core/download_manager_delegate_qt.cpp8
-rw-r--r--src/core/net/client_cert_override.cpp150
-rw-r--r--src/core/net/client_cert_override.h (renamed from src/core/client_cert_override_p.h)14
-rw-r--r--src/core/net/client_cert_store_data.cpp (renamed from src/core/client_cert_override_key.cpp)112
-rw-r--r--src/core/net/client_cert_store_data.h (renamed from src/core/client_cert_override_key_p.h)42
-rw-r--r--src/core/net/network_delegate_qt.cpp185
-rw-r--r--src/core/net/proxy_config_service_qt.cpp14
-rw-r--r--src/core/net/proxy_config_service_qt.h10
-rw-r--r--src/core/net/url_request_notification.cpp187
-rw-r--r--src/core/net/url_request_notification.h85
-rw-r--r--src/core/ozone/gl_context_qt.cpp7
-rw-r--r--src/core/ozone/gl_surface_glx_qt.cpp2
-rw-r--r--src/core/permission_manager_qt.cpp57
-rw-r--r--src/core/platform_notification_service_qt.cpp208
-rw-r--r--src/core/platform_notification_service_qt.h92
-rw-r--r--src/core/profile_adapter.cpp2
-rw-r--r--src/core/profile_adapter.h16
-rw-r--r--src/core/profile_adapter_client.h4
-rw-r--r--src/core/profile_io_data_qt.cpp187
-rw-r--r--src/core/profile_io_data_qt.h10
-rw-r--r--src/core/profile_qt.cpp10
-rw-r--r--src/core/qtwebengine.gni1
-rw-r--r--src/core/render_widget_host_view_qt.cpp127
-rw-r--r--src/core/render_widget_host_view_qt.h15
-rw-r--r--src/core/render_widget_host_view_qt_delegate.h7
-rw-r--r--src/core/resource_context_qt.h1
-rw-r--r--src/core/type_conversion.h5
-rw-r--r--src/core/user_notification_controller.cpp219
-rw-r--r--src/core/user_notification_controller.h114
-rw-r--r--src/core/web_contents_adapter.cpp13
-rw-r--r--src/core/web_contents_adapter.h1
-rw-r--r--src/core/web_contents_adapter_client.h1
-rw-r--r--src/core/web_contents_delegate_qt.cpp5
-rw-r--r--src/core/web_contents_delegate_qt.h1
-rw-r--r--src/core/web_engine_context.cpp71
-rw-r--r--src/core/web_engine_context.h2
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp50
-rw-r--r--src/webengine/api/qquickwebengineprofile.h6
-rw-r--r--src/webengine/api/qquickwebengineprofile_p.h2
-rw-r--r--src/webengine/api/qquickwebengineview.cpp9
-rw-r--r--src/webengine/api/qquickwebengineview_p.h3
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h1
-rw-r--r--src/webengine/doc/src/qtwebengine-features.qdoc10
-rw-r--r--src/webengine/doc/src/webengineview_lgpl.qdoc2
-rw-r--r--src/webengine/plugin/plugin.cpp3
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quick.cpp34
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quick.h4
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp9
-rw-r--r--src/webengine/render_widget_host_view_qt_delegate_quickwindow.h3
-rw-r--r--src/webenginewidgets/api/qwebenginenotificationpresenter.cpp101
-rw-r--r--src/webenginewidgets/api/qwebenginenotificationpresenter_p.h83
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp21
-rw-r--r--src/webenginewidgets/api/qwebenginepage.h6
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h1
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp58
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.h9
-rw-r--r--src/webenginewidgets/api/qwebengineprofile_p.h6
-rw-r--r--src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc18
-rw-r--r--src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc4
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp25
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h4
-rw-r--r--src/webenginewidgets/webenginewidgets.pro2
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp23
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp18
-rw-r--r--tests/auto/quick/qmltests/data/tst_notification.qml116
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro1
-rw-r--r--tests/auto/quick/qquickwebengineview/BLACKLIST4
-rw-r--r--tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp40
-rw-r--r--tests/auto/shared/data/notification.html70
-rw-r--r--tests/auto/widgets/origins/tst_origins.cpp5
-rw-r--r--tests/auto/widgets/proxypac/proxypac.pro24
-rw-r--r--tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp1
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp95
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc3
-rw-r--r--tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp16
-rw-r--r--tests/auto/widgets/qwebengineview/BLACKLIST3
-rw-r--r--tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp23
-rw-r--r--tests/auto/widgets/widgets.pro6
-rw-r--r--tests/quicktestbrowser/ApplicationRoot.qml1
-rw-r--r--tests/quicktestbrowser/BrowserWindow.qml12
-rw-r--r--tests/quicktestbrowser/FeaturePermissionBar.qml29
105 files changed, 3067 insertions, 802 deletions
diff --git a/dist/changes-5.12.1 b/dist/changes-5.12.1
new file mode 100644
index 000000000..44dfdd5c7
--- /dev/null
+++ b/dist/changes-5.12.1
@@ -0,0 +1,78 @@
+Qt 5.12.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0.
+
+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.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+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.
+
+****************************************************************************
+* Qt 5.12.1 Changes *
+****************************************************************************
+
+Chromium
+--------
+
+ - Security fixes from Chromium up to version 71.0.3578.94, including:
+ * CVE-2018-17480
+ * CVE-2018-17481
+ * CVE-2018-18335
+ * CVE-2018-18336
+ * CVE-2018-18337
+ * CVE-2018-18338
+ * CVE-2018-18339
+ * CVE-2018-18340
+ * CVE-2018-18341
+ * CVE-2018-18342
+ * CVE-2018-18343
+ * CVE-2018-18345
+ * CVE-2018-18347
+ * CVE-2018-18349
+ * CVE-2018-18350
+ * CVE-2018-18355
+ * CVE-2018-18356
+ * CVE-2018-18357
+ * CVE-2018-18358
+ * CVE-2018-18359
+ * Security Bug 839250
+ * Security Bug 851821
+ * Security Bug 869067
+ * Security Bug 877843
+ * Security Bug 879965
+ * Security Bug 880665
+ * Security Bug 882270
+ * Security Bug 892643
+ * Security Bug 895885
+ * Security Bug 900910
+ - Fixed x86-32 builds on GCC 8.
+ - Fixed building on ARM hosts.
+
+
+General
+-------
+
+ * Enabled idle detection and sleep inhibition on Linux and macOS.
+ * [QTBUG-66262] Improved suggested file name of downloads when conflicts arise.
+ * [QTBUG-71322] Enabled bilinear filtering of textures in software rendering mode.
+ * [QTBUG-71370] Fixed autoscrolling regression.
+ * [QTBUG-71895] Fixed crash when calling clearHttpCache().
+ * [QTBUG-72260] Fixed crash on requestInterceptor changes.
+ * [QTBUG-72654] Fixed Event.timeStamp being 0.
+ * [QTBUG-72655] Fixed some JS properties of dead key event.
+
+
+QtQuickWebEngine
+----------------
+
+ * [QTBUG-72299] Fixed problem with blank view after reuse.
diff --git a/examples/webenginewidgets/simplebrowser/browserwindow.cpp b/examples/webenginewidgets/simplebrowser/browserwindow.cpp
index 4351dfe71..5d00cd19a 100644
--- a/examples/webenginewidgets/simplebrowser/browserwindow.cpp
+++ b/examples/webenginewidgets/simplebrowser/browserwindow.cpp
@@ -62,6 +62,7 @@
#include <QMenuBar>
#include <QMessageBox>
#include <QProgressBar>
+#include <QScreen>
#include <QStatusBar>
#include <QToolBar>
#include <QVBoxLayout>
@@ -143,7 +144,7 @@ BrowserWindow::BrowserWindow(Browser *browser, QWebEngineProfile *profile, bool
QSize BrowserWindow::sizeHint() const
{
- QRect desktopRect = QApplication::desktop()->screenGeometry();
+ QRect desktopRect = QApplication::primaryScreen()->geometry();
QSize size = desktopRect.size() * qreal(0.9);
return size;
}
diff --git a/examples/webenginewidgets/simplebrowser/webpage.cpp b/examples/webenginewidgets/simplebrowser/webpage.cpp
index e44410284..99849c77d 100644
--- a/examples/webenginewidgets/simplebrowser/webpage.cpp
+++ b/examples/webenginewidgets/simplebrowser/webpage.cpp
@@ -138,7 +138,7 @@ inline QString questionForFeature(QWebEnginePage::Feature feature)
case QWebEnginePage::DesktopAudioVideoCapture:
return WebPage::tr("Allow %1 to capture audio and video of your desktop?");
case QWebEnginePage::Notifications:
- return QString();
+ return WebPage::tr("Allow %1 to show notification on your desktop?");
}
return QString();
}
diff --git a/src/3rdparty b/src/3rdparty
-Subproject 5a76a0a325a041dab3c93943c99835d3e929762
+Subproject 8d510183ca27142801b56bb50d63cbb2a92d433
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index b5bb93847..4d3ddcc8e 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -38,6 +38,7 @@ HEADERS = \
qwebenginecookiestore.h \
qwebenginecookiestore_p.h \
qwebenginehttprequest.h \
+ qwebenginenotification.h \
qwebenginequotarequest.h \
qwebengineregisterprotocolhandlerrequest.h \
qwebengineurlrequestinterceptor.h \
@@ -49,8 +50,10 @@ HEADERS = \
SOURCES = \
qtwebenginecoreglobal.cpp \
+ qwebengineclientcertificatestore.cpp \
qwebenginecookiestore.cpp \
qwebenginehttprequest.cpp \
+ qwebenginenotification.cpp \
qwebenginequotarequest.cpp \
qwebengineregisterprotocolhandlerrequest.cpp \
qwebengineurlrequestinfo.cpp \
diff --git a/src/core/qwebengineclientcertificatestore.cpp b/src/core/api/qwebengineclientcertificatestore.cpp
index 08f4389d7..850dd16d7 100644
--- a/src/core/qwebengineclientcertificatestore.cpp
+++ b/src/core/api/qwebengineclientcertificatestore.cpp
@@ -37,34 +37,9 @@
**
****************************************************************************/
-#include "api/qwebengineclientcertificatestore.h"
-#include "client_cert_override_key_p.h"
-#include "client_cert_override_p.h"
+#include "qwebengineclientcertificatestore.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/task/post_task.h"
-#include "base/callback_forward.h"
-
-#include "net/ssl/client_cert_store.h"
-#include "net/ssl/ssl_cert_request_info.h"
-#include "net/cert/x509_certificate.h"
-
-#include "third_party/boringssl/src/include/openssl/pem.h"
-#include "third_party/boringssl/src/include/openssl/err.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-
-#if defined(USE_NSS_CERTS)
-#include "net/ssl/client_cert_store_nss.h"
-#endif
-
-#if defined(OS_WIN)
-#include "net/ssl/client_cert_store_win.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "net/ssl/client_cert_store_mac.h"
-#endif
+#include "net/client_cert_store_data.h"
#include <QByteArray>
#include <QList>
@@ -73,19 +48,7 @@ QT_BEGIN_NAMESPACE
#if QT_CONFIG(ssl)
-typedef struct OverrideData {
- QSslKey key;
- QSslCertificate certificate;
- scoped_refptr<net::X509Certificate> certPtr;
- scoped_refptr<net::SSLPrivateKey> keyPtr;
-} OverrideData;
-
-struct QWebEngineClientCertificateStoreData {
- QList<OverrideData*> deletedCerts;
-};
-
-static QList<OverrideData*> ClientCertOverrideData;
-QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::m_instance = NULL;
+QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::m_instance = nullptr;
/*!
\class QWebEngineClientCertificateStore::Entry
@@ -107,8 +70,8 @@ QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::m_instance =
*/
QWebEngineClientCertificateStore::QWebEngineClientCertificateStore()
+ : d_ptr(new QtWebEngineCore::ClientCertificateStoreData)
{
- this->d_ptr = new QWebEngineClientCertificateStoreData;
}
/*!
@@ -119,9 +82,6 @@ QWebEngineClientCertificateStore::~QWebEngineClientCertificateStore()
{
// Just in case user has not deleted in-memory certificates
clear();
-
- qDeleteAll(d_ptr->deletedCerts);
- delete d_ptr;
}
/*!
@@ -141,17 +101,7 @@ QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::getInstance(
void QWebEngineClientCertificateStore::add(const QSslCertificate &certificate, const QSslKey &privateKey)
{
-
- QByteArray sslKeyInBytes = privateKey.toPem();
- QByteArray certInBytes = certificate.toDer();
-
- OverrideData* data = new OverrideData;
- data->keyPtr = net::WrapOpenSSLPrivateKey(sslKeyInBytes);
- data->certPtr = net::X509Certificate::CreateFromBytes(
- certInBytes.data(), certInBytes.length());
- data->key = privateKey;
- data->certificate = certificate;
- ClientCertOverrideData.append(data);
+ d_ptr->add(certificate, privateKey);
}
/*!
@@ -162,7 +112,7 @@ void QWebEngineClientCertificateStore::add(const QSslCertificate &certificate, c
QList<QWebEngineClientCertificateStore::Entry> QWebEngineClientCertificateStore::toList() const
{
QList<Entry> certificateList;
- for (auto data : ClientCertOverrideData) {
+ for (auto data : qAsConst(d_ptr->addedCerts)) {
Entry entry;
entry.certificate = data->certificate;
entry.privateKey = data->key;
@@ -178,13 +128,15 @@ QList<QWebEngineClientCertificateStore::Entry> QWebEngineClientCertificateStore:
void QWebEngineClientCertificateStore::remove(Entry entry)
{
- QMutableListIterator<OverrideData*> iterator(ClientCertOverrideData);
- while (iterator.hasNext()) {
- auto overrideData = iterator.next();
+ auto it = d_ptr->addedCerts.begin();
+ while (it != d_ptr->addedCerts.end()) {
+ auto *overrideData = *it;
if (entry.certificate.toDer() == overrideData->certificate.toDer()) {
d_ptr->deletedCerts.append(overrideData);
- iterator.remove();
+ it = d_ptr->addedCerts.erase(it);
+ continue;
}
+ ++it;
}
}
@@ -194,95 +146,10 @@ void QWebEngineClientCertificateStore::remove(Entry entry)
void QWebEngineClientCertificateStore::clear()
{
- for (auto data : ClientCertOverrideData)
- d_ptr->deletedCerts.append(data);
- ClientCertOverrideData.clear();
+ d_ptr->deletedCerts.append(d_ptr->addedCerts);
+ d_ptr->addedCerts.clear();
}
#endif // QT_CONFIG(ssl)
QT_END_NAMESPACE
-
-namespace net {
-
-namespace {
-
-class ClientCertIdentityOverride : public ClientCertIdentity {
-public:
- ClientCertIdentityOverride(
- scoped_refptr<net::X509Certificate> cert,
- scoped_refptr<net::SSLPrivateKey> key)
- : ClientCertIdentity(std::move(cert)),
- key_(std::move(key)) {}
- ~ClientCertIdentityOverride() override = default;
-
- void AcquirePrivateKey(
- const base::Callback<void(scoped_refptr<SSLPrivateKey>)>&
- private_key_callback) override
- {
- private_key_callback.Run(key_);
- }
-
-#if defined(OS_MACOSX)
- SecIdentityRef sec_identity_ref() const override
- {
- return nullptr;
- }
-#endif
-
-private:
- scoped_refptr<net::SSLPrivateKey> key_;
-};
-
-} // namespace
-
-
-ClientCertOverrideStore::ClientCertOverrideStore()
- : ClientCertStore()
-{
-}
-
-ClientCertOverrideStore::~ClientCertOverrideStore()
-{
-}
-
-void ClientCertOverrideStore::GetClientCerts(const SSLCertRequestInfo &cert_request_info,
- const ClientCertListCallback &callback)
-{
-#if QT_CONFIG(ssl)
- // Look for certificates in memory store
- for (int i = 0; i < ClientCertOverrideData.length(); i++) {
- scoped_refptr<net::X509Certificate> cert = ClientCertOverrideData[i]->certPtr;
- if (cert != NULL && cert->IsIssuedByEncoded(cert_request_info.cert_authorities)) {
- ClientCertIdentityList selected_identities;
- selected_identities.push_back(std::make_unique<ClientCertIdentityOverride>(cert, ClientCertOverrideData[i]->keyPtr));
- callback.Run(std::move(selected_identities));
- return;
- }
- }
-#endif // QT_CONFIG(ssl)
-
- // Continue with native cert store if matching certificate is not found in memory
- std::unique_ptr<net::ClientCertStore> store = getNativeStore();
- if (store != NULL) {
- store->GetClientCerts(cert_request_info, callback);
- return;
- }
-
- callback.Run(ClientCertIdentityList());
- return;
-}
-
-std::unique_ptr<net::ClientCertStore> ClientCertOverrideStore::getNativeStore()
-{
-#if defined(USE_NSS_CERTS)
- return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory()));
-#elif defined(OS_WIN)
- return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
-#elif defined(OS_MACOSX)
- return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
-#else
- return nullptr;
-#endif
-}
-}
diff --git a/src/core/api/qwebengineclientcertificatestore.h b/src/core/api/qwebengineclientcertificatestore.h
index 6ba998465..c0bd66e2b 100644
--- a/src/core/api/qwebengineclientcertificatestore.h
+++ b/src/core/api/qwebengineclientcertificatestore.h
@@ -42,14 +42,19 @@
#include <QtWebEngineCore/qtwebenginecoreglobal.h>
+#include <QtCore/qscopedpointer.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qsslkey.h>
+namespace QtWebEngineCore {
+class ClientCertOverrideStore;
+struct ClientCertificateStoreData;
+}
+
QT_BEGIN_NAMESPACE
#if QT_CONFIG(ssl)
-struct QWebEngineClientCertificateStoreData;
class QWEBENGINECORE_EXPORT QWebEngineClientCertificateStore {
@@ -66,12 +71,13 @@ public:
void clear();
private:
+ friend class QtWebEngineCore::ClientCertOverrideStore;
static QWebEngineClientCertificateStore *m_instance;
Q_DISABLE_COPY(QWebEngineClientCertificateStore)
QWebEngineClientCertificateStore();
~QWebEngineClientCertificateStore();
- QWebEngineClientCertificateStoreData *d_ptr;
+ QScopedPointer<QtWebEngineCore::ClientCertificateStoreData> d_ptr;
};
#endif // QT_CONFIG(ssl)
diff --git a/src/core/api/qwebenginenotification.cpp b/src/core/api/qwebenginenotification.cpp
new file mode 100644
index 000000000..0b91cf273
--- /dev/null
+++ b/src/core/api/qwebenginenotification.cpp
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwebenginenotification.h"
+
+#include "user_notification_controller.h"
+
+#include <QExplicitlySharedDataPointer>
+
+QT_BEGIN_NAMESPACE
+
+using QtWebEngineCore::UserNotificationController;
+
+/*!
+ \class QWebEngineNotification
+ \brief The QWebEngineNotification class encapsulates the data of an HTML5 web notification.
+ \since 5.13
+
+ \inmodule QtWebEngineCore
+
+ This class contains the information and API for HTML5 desktop and push notifications.
+*/
+
+class QWebEngineNotificationPrivate : public UserNotificationController::Client {
+public:
+ QWebEngineNotificationPrivate(QWebEngineNotification *q, const QSharedPointer<UserNotificationController> &controller)
+ : controller(controller)
+ , q(q)
+ {
+ controller->setClient(this);
+ }
+ ~QWebEngineNotificationPrivate() override
+ {
+ if (controller->client() == this)
+ controller->setClient(0);
+ }
+
+ // UserNotificationController::Client:
+ virtual void notificationClosed(const UserNotificationController *) Q_DECL_OVERRIDE
+ {
+ Q_EMIT q->closed();
+ }
+
+ QSharedPointer<UserNotificationController> controller;
+ QWebEngineNotification *q;
+};
+
+
+/*!
+ Creates a null QWebEngineNotification.
+
+ \sa isNull()
+*/
+QWebEngineNotification::QWebEngineNotification() { }
+
+/*! \internal
+*/
+QWebEngineNotification::QWebEngineNotification(const QSharedPointer<UserNotificationController> &controller)
+ : d_ptr(new QWebEngineNotificationPrivate(this, controller))
+{ }
+
+/*! \internal
+*/
+QWebEngineNotification::QWebEngineNotification(const QWebEngineNotification &other)
+ : QObject()
+ , d_ptr(new QWebEngineNotificationPrivate(this, other.d_ptr->controller))
+{ }
+
+/*! \internal
+*/
+QWebEngineNotification::~QWebEngineNotification()
+{
+}
+
+/*! \internal
+*/
+const QWebEngineNotification &QWebEngineNotification::operator=(const QWebEngineNotification &other)
+{
+ d_ptr.reset(new QWebEngineNotificationPrivate(this, other.d_ptr->controller));
+ return *this;
+}
+
+/*!
+ Returns \c true if the two notifications belong to the same message chain.
+ That is, if their tag() and origin() are the same. This means one is
+ a replacement or an update of the \a other.
+
+ \sa tag(), origin()
+*/
+bool QWebEngineNotification::matches(const QWebEngineNotification &other) const
+{
+ if (!d_ptr)
+ return !other.d_ptr;
+ if (!other.d_ptr)
+ return false;
+ return tag() == other.tag() && origin() == other.origin();
+}
+
+/*!
+ \property QWebEngineNotification::title
+ \brief The title of the notification.
+ \sa message()
+*/
+QString QWebEngineNotification::title() const
+{
+ Q_D(const QWebEngineNotification);
+ return d ? d->controller->title() : QString();
+}
+
+/*!
+ \property QWebEngineNotification::message
+ \brief The body of the notification message.
+ \sa title()
+*/
+
+QString QWebEngineNotification::message() const
+{
+ Q_D(const QWebEngineNotification);
+ return d ? d->controller->body() : QString();
+}
+
+/*!
+ \property QWebEngineNotification::tag
+ \brief The tag of the notification message.
+
+ New notifications that have the same tag and origin URL as an existing
+ one should replace or update the old notification with the same tag.
+
+ \sa matches()
+*/
+QString QWebEngineNotification::tag() const
+{
+ Q_D(const QWebEngineNotification);
+ return d ? d->controller->tag() : QString();
+}
+
+/*!
+ \property QWebEngineNotification::origin
+ \brief The URL of the page sending the notification.
+*/
+
+QUrl QWebEngineNotification::origin() const
+{
+ Q_D(const QWebEngineNotification);
+ return d ? d->controller->origin() : QUrl();
+}
+
+/*!
+ \property QWebEngineNotification::icon
+ \brief The icon to be shown with the notification.
+
+ If no icon is set by the sender, an null QIcon is returned.
+*/
+QIcon QWebEngineNotification::icon() const
+{
+ Q_D(const QWebEngineNotification);
+ return d ? d->controller->icon() : QIcon();
+}
+
+/*!
+ \property QWebEngineNotification::language
+ \brief The primary language for the notification's title and body.
+
+ Its value is a valid BCP 47 language tag, or the empty string.
+
+ \sa title(), message()
+*/
+QString QWebEngineNotification::language() const
+{
+ Q_D(const QWebEngineNotification);
+ return d ? d->controller->language() : QString();
+}
+
+/*!
+ \property QWebEngineNotification::direction
+ \brief The text direction for the notification's title and body.
+ \sa title(), message()
+*/
+QWebEngineNotification::Direction QWebEngineNotification::direction() const
+{
+ Q_D(const QWebEngineNotification);
+ return d ? static_cast<Direction>(d->controller->direction()) : DirectionAuto;
+}
+
+/*!
+ Returns \c true if the notification is a default constructed null notification.
+*/
+bool QWebEngineNotification::isNull() const
+{
+ return d_ptr.isNull();
+}
+
+/*!
+ Creates and dispatches a JavaScript \e {show event} on notification.
+
+ Should be called by the notification platform when the notification has been shown to user.
+*/
+void QWebEngineNotification::show() const
+{
+ Q_D(const QWebEngineNotification);
+ if (d)
+ d->controller->notificationDisplayed();
+}
+
+/*!
+ Creates and dispatches a JavaScript \e {click event} on notification.
+
+ Should be called by the notification platform when the notification is activated by the user.
+*/
+void QWebEngineNotification::click() const
+{
+ Q_D(const QWebEngineNotification);
+ if (d)
+ d->controller->notificationClicked();
+}
+
+/*!
+ Creates and dispatches a JavaScript \e {close event} on notification.
+
+ Should be called by the notification platform when the notification is closed,
+ either by the underlying platform or by the user.
+*/
+void QWebEngineNotification::close() const
+{
+ Q_D(const QWebEngineNotification);
+ if (d)
+ d->controller->notificationClosed();
+}
+
+/*!
+ \fn void QWebEngineNotification::closed()
+
+ This signal is emitted when the web page calls close steps for the notification,
+ and it no longer needs to be shown.
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qwebenginenotification.cpp"
diff --git a/src/core/api/qwebenginenotification.h b/src/core/api/qwebenginenotification.h
new file mode 100644
index 000000000..b6b7414f9
--- /dev/null
+++ b/src/core/api/qwebenginenotification.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBENGINENOTIFICATION_H
+#define QWEBENGINENOTIFICATION_H
+
+#include <QtWebEngineCore/qtwebenginecoreglobal.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QUrl>
+#include <QtGui/QIcon>
+
+namespace QtWebEngineCore {
+class UserNotificationController;
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWebEngineNotificationPrivate;
+
+class QWEBENGINECORE_EXPORT QWebEngineNotification : public QObject {
+ Q_OBJECT
+ Q_PROPERTY(QUrl origin READ origin CONSTANT FINAL)
+ Q_PROPERTY(QIcon icon READ icon CONSTANT FINAL)
+ Q_PROPERTY(QString title READ title CONSTANT FINAL)
+ Q_PROPERTY(QString message READ message CONSTANT FINAL)
+ Q_PROPERTY(QString tag READ tag CONSTANT FINAL)
+ Q_PROPERTY(QString language READ language CONSTANT FINAL)
+ Q_PROPERTY(Direction direction READ direction CONSTANT FINAL)
+
+public:
+ QWebEngineNotification();
+ QWebEngineNotification(const QWebEngineNotification &);
+ virtual ~QWebEngineNotification();
+ const QWebEngineNotification &operator=(const QWebEngineNotification &);
+
+ enum Direction {
+ LeftToRight = Qt::LeftToRight,
+ RightToLeft = Qt::RightToLeft,
+ DirectionAuto = Qt::LayoutDirectionAuto
+ };
+ Q_ENUM(Direction)
+
+ bool matches(const QWebEngineNotification &) const;
+
+ QUrl origin() const;
+ QIcon icon() const;
+ QString title() const;
+ QString message() const;
+ QString tag() const;
+ QString language() const;
+ Direction direction() const;
+
+ bool isNull() const;
+
+public Q_SLOTS:
+ void show() const;
+ void click() const;
+ void close() const;
+
+Q_SIGNALS:
+ void closed();
+
+private:
+ QWebEngineNotification(const QSharedPointer<QtWebEngineCore::UserNotificationController> &);
+ Q_DECLARE_PRIVATE(QWebEngineNotification)
+ QScopedPointer<QWebEngineNotificationPrivate> d_ptr;
+ friend class QQuickWebEngineProfilePrivate;
+ friend class QWebEngineProfilePrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWEBENGINENOTIFICATION_H
diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp
index c3e5b5445..dc2d07740 100644
--- a/src/core/api/qwebengineurlrequestinfo.cpp
+++ b/src/core/api/qwebengineurlrequestinfo.cpp
@@ -96,8 +96,8 @@ ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::OtherNavigation, Q
interceptor on the profile enables intercepting, blocking, and modifying URL requests
before they reach the networking stack of Chromium.
- You can install the interceptor on a profile via QWebEngineProfile::setRequestInterceptor()
- or QQuickWebEngineProfile::setRequestInterceptor().
+ You can install the interceptor on a profile via QWebEngineProfile::setUrlRequestInterceptor()
+ or QQuickWebEngineProfile::setUrlRequestInterceptor().
When using the \l{Qt WebEngine Widgets Module}, \l{QWebEnginePage::acceptNavigationRequest()}
offers further options to accept or block requests.
@@ -115,11 +115,7 @@ ASSERT_ENUMS_MATCH(QtWebEngineCore::WebContentsAdapterClient::OtherNavigation, Q
\fn void QWebEngineUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)
Reimplementing this virtual function makes it possible to intercept URL
- requests. For interceptors installed on a QWebEngineProfile, the function is executed
- on the I/O thread, and thus it may not be thread-safe to interact with pages. If the
- interceptor was installed on a QWebEnginePage, the function is executed on the main
- application thread, and can safely interact with other user classes. Both versions will
- be stalling the URL request until handled.
+ requests. This method will be stalling the URL request until handled.
\a info contains the information about the URL request and will track internally
whether its members have been altered.
diff --git a/src/core/api/qwebengineurlrequestinterceptor.h b/src/core/api/qwebengineurlrequestinterceptor.h
index dc2a15ee3..2b07681ca 100644
--- a/src/core/api/qwebengineurlrequestinterceptor.h
+++ b/src/core/api/qwebengineurlrequestinterceptor.h
@@ -55,7 +55,7 @@ class QWEBENGINECORE_EXPORT QWebEngineUrlRequestInterceptor : public QObject
Q_OBJECT
Q_DISABLE_COPY(QWebEngineUrlRequestInterceptor)
public:
- explicit QWebEngineUrlRequestInterceptor(QObject *p = Q_NULLPTR)
+ explicit QWebEngineUrlRequestInterceptor(QObject *p = nullptr)
: QObject (p)
{
}
diff --git a/src/core/api/qwebengineurlscheme.cpp b/src/core/api/qwebengineurlscheme.cpp
index d63599163..9f7288f2d 100644
--- a/src/core/api/qwebengineurlscheme.cpp
+++ b/src/core/api/qwebengineurlscheme.cpp
@@ -39,7 +39,9 @@
#include "qwebengineurlscheme.h"
-#include <url/url_util_qt.h>
+#include "url/url_util_qt.h"
+
+#include <QtDebug>
QT_BEGIN_NAMESPACE
@@ -59,6 +61,8 @@ ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ServiceWorkersAllowed, url::CustomScheme
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ViewSourceAllowed, url::CustomScheme::ViewSourceAllowed)
ASSERT_ENUMS_MATCH(QWebEngineUrlScheme::ContentSecurityPolicyIgnored, url::CustomScheme::ContentSecurityPolicyIgnored)
+static bool g_schemesLocked = false;
+
class QWebEngineUrlSchemePrivate : public QSharedData
, public url::CustomScheme
{
@@ -357,6 +361,28 @@ void QWebEngineUrlScheme::setFlags(Flags newValue)
*/
void QWebEngineUrlScheme::registerScheme(const QWebEngineUrlScheme &scheme)
{
+ if (scheme.d->name.empty()) {
+ qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty";
+ return;
+ }
+
+ bool needsPort = scheme.d->has_port_component();
+ bool hasPort = scheme.d->default_port != url::PORT_UNSPECIFIED;
+ if (needsPort && !hasPort) {
+ qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "needs a default port";
+ return;
+ }
+
+ if (url::CustomScheme::FindScheme(scheme.d->name)) {
+ qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "already registered";
+ return;
+ }
+
+ if (g_schemesLocked) {
+ qWarning() << "QWebEngineUrlScheme::registerScheme: Too late to register scheme" << scheme.name();
+ return;
+ }
+
url::CustomScheme::AddScheme(*scheme.d);
}
@@ -374,4 +400,9 @@ QWebEngineUrlScheme QWebEngineUrlScheme::schemeByName(const QByteArray &name)
return QWebEngineUrlScheme();
}
+void QWebEngineUrlScheme::lockSchemes()
+{
+ g_schemesLocked = true;
+}
+
QT_END_NAMESPACE
diff --git a/src/core/api/qwebengineurlscheme.h b/src/core/api/qwebengineurlscheme.h
index 88a8f5065..da3010335 100644
--- a/src/core/api/qwebengineurlscheme.h
+++ b/src/core/api/qwebengineurlscheme.h
@@ -46,6 +46,8 @@
#include <QtCore/qobjectdefs.h>
#include <QtCore/qshareddata.h>
+namespace QtWebEngineCore { class WebEngineContext; }
+
QT_BEGIN_NAMESPACE
class QWebEngineUrlSchemePrivate;
@@ -106,6 +108,8 @@ public:
static QWebEngineUrlScheme schemeByName(const QByteArray &name);
private:
+ friend QtWebEngineCore::WebEngineContext;
+ static void lockSchemes();
QWebEngineUrlScheme(QWebEngineUrlSchemePrivate *d);
QSharedDataPointer<QWebEngineUrlSchemePrivate> d;
};
diff --git a/src/core/chromium_overrides.cpp b/src/core/chromium_overrides.cpp
index c25d6dda9..09058301b 100644
--- a/src/core/chromium_overrides.cpp
+++ b/src/core/chromium_overrides.cpp
@@ -37,8 +37,6 @@
**
****************************************************************************/
-#include "chromium_overrides.h"
-
#include "ozone/gl_context_qt.h"
#include "qtwebenginecoreglobal_p.h"
#include "web_contents_view_qt.h"
@@ -72,27 +70,6 @@
#include "net/ssl/openssl_client_key_store.h"
#endif
-namespace QtWebEngineCore {
-void GetScreenInfoFromNativeWindow(QWindow* window, content::ScreenInfo* results)
-{
- QScreen* screen = window->screen();
- if (!screen)
- return;
- content::ScreenInfo r;
- r.device_scale_factor = screen->devicePixelRatio();
- r.depth_per_component = 8;
- r.depth = screen->depth();
- r.is_monochrome = (r.depth == 1);
-
- QRect screenGeometry = screen->geometry();
- r.rect = gfx::Rect(screenGeometry.x(), screenGeometry.y(), screenGeometry.width(), screenGeometry.height());
- QRect available = screen->availableGeometry();
- r.available_rect = gfx::Rect(available.x(), available.y(), available.width(), available.height());
- *results = r;
-}
-
-} // namespace QtWebEngineCore
-
void *GetQtXDisplay()
{
return GLContextHelper::getXDisplay();
@@ -113,13 +90,6 @@ WebContentsView* CreateWebContentsView(WebContentsImpl *web_contents,
return rv;
}
-// static
-void WebContentsView::GetDefaultScreenInfo(content::ScreenInfo* results)
-{
- QWindow dummy;
- QtWebEngineCore::GetScreenInfoFromNativeWindow(&dummy, results);
-}
-
#if defined(Q_OS_MACOS)
std::string getQtPrefix()
{
diff --git a/src/core/command_line_pref_store_qt.cpp b/src/core/command_line_pref_store_qt.cpp
new file mode 100644
index 000000000..5c5c82e1a
--- /dev/null
+++ b/src/core/command_line_pref_store_qt.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "command_line_pref_store_qt.h"
+
+#include "chrome/common/chrome_switches.h"
+#include "components/proxy_config/proxy_config_dictionary.h"
+#include "components/proxy_config/proxy_config_pref_names.h"
+#include "content/public/common/content_switches.h"
+#include <QDebug>
+
+CommandLinePrefStoreQt::CommandLinePrefStoreQt(const base::CommandLine *commandLine)
+ : CommandLinePrefStore(commandLine)
+{
+
+ if (commandLine->HasSwitch(switches::kNoProxyServer)) {
+ SetValue(proxy_config::prefs::kProxy,
+ std::make_unique<base::Value>(ProxyConfigDictionary::CreateDirect()),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ } else if (commandLine->HasSwitch(switches::kProxyPacUrl)) {
+ std::string pac_script_url =
+ commandLine->GetSwitchValueASCII(switches::kProxyPacUrl);
+ SetValue(proxy_config::prefs::kProxy,
+ std::make_unique<base::Value>(ProxyConfigDictionary::CreatePacScript(
+ pac_script_url, false)),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ } else if (commandLine->HasSwitch(switches::kProxyAutoDetect)) {
+ SetValue(proxy_config::prefs::kProxy,
+ std::make_unique<base::Value>(
+ ProxyConfigDictionary::CreateAutoDetect()),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ } else if (commandLine->HasSwitch(switches::kProxyServer)) {
+ std::string proxy_server =
+ commandLine->GetSwitchValueASCII(switches::kProxyServer);
+ std::string bypass_list =
+ commandLine->GetSwitchValueASCII(switches::kProxyBypassList);
+ SetValue(
+ proxy_config::prefs::kProxy,
+ std::make_unique<base::Value>(ProxyConfigDictionary::CreateFixedServers(
+ proxy_server, bypass_list)),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ }
+
+ if (commandLine->HasSwitch(switches::kNoProxyServer) && (commandLine->HasSwitch(switches::kProxyAutoDetect) || commandLine->HasSwitch(switches::kProxyServer) || commandLine->HasSwitch(switches::kProxyPacUrl) || commandLine->HasSwitch(switches::kProxyBypassList))) {
+ qWarning("Additional command-line proxy switches specified when --%s was also specified",
+ qPrintable(switches::kNoProxyServer));
+ }
+}
+
+CommandLinePrefStoreQt::~CommandLinePrefStoreQt() = default;
diff --git a/src/core/chromium_overrides.h b/src/core/command_line_pref_store_qt.h
index b27bf309c..a509f8ca9 100644
--- a/src/core/chromium_overrides.h
+++ b/src/core/command_line_pref_store_qt.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -37,18 +37,20 @@
**
****************************************************************************/
-#ifndef CHROMIUM_OVERRIDES_H
-#define CHROMIUM_OVERRIDES_H
+#ifndef COMMAND_LINE_PREF_STORE_QT_H
+#define COMMAND_LINE_PREF_STORE_QT_H
-#include "content/public/common/screen_info.h"
-#include <QtGlobal>
+#include "base/command_line.h"
+#include "components/prefs/command_line_pref_store.h"
-QT_BEGIN_NAMESPACE
-class QWindow;
-QT_END_NAMESPACE
+class CommandLinePrefStoreQt : public CommandLinePrefStore
+{
+public:
+ explicit CommandLinePrefStoreQt(const base::CommandLine *commandLine);
-namespace QtWebEngineCore {
-void GetScreenInfoFromNativeWindow(QWindow* window, content::ScreenInfo* results);
-}
+protected:
+ ~CommandLinePrefStoreQt() override;
+ DISALLOW_COPY_AND_ASSIGN(CommandLinePrefStoreQt);
+};
-#endif
+#endif // COMMAND_LINE_PREF_STORE_QT_H
diff --git a/src/core/compositor/compositor_resource.h b/src/core/compositor/compositor_resource.h
index c40ce3d5e..f7df2ab59 100644
--- a/src/core/compositor/compositor_resource.h
+++ b/src/core/compositor/compositor_resource.h
@@ -71,8 +71,9 @@ using CompositorResourceId = quint32;
//
// - A committed resource's fields may not be updated and are safe to use from
// other threads without synchronization (unless noted otherwise).
-struct CompositorResource : viz::TransferableResource
+class CompositorResource : public viz::TransferableResource
{
+public:
CompositorResource(const viz::TransferableResource &tr) : viz::TransferableResource(tr) {}
// Counts the number of times this resource has been encountered in
diff --git a/src/core/compositor/delegated_frame_node.cpp b/src/core/compositor/delegated_frame_node.cpp
index e2b6714a1..4fb05051b 100644
--- a/src/core/compositor/delegated_frame_node.cpp
+++ b/src/core/compositor/delegated_frame_node.cpp
@@ -619,7 +619,7 @@ void DelegatedFrameNode::commit(const viz::CompositorFrame &pendingFrame,
QScopedPointer<DelegatedNodeTreeHandler> nodeHandler;
- const QSizeF viewportSizeInPt = apiDelegate->screenRect().size();
+ const QSizeF viewportSizeInPt = apiDelegate->viewGeometry().size();
const QSizeF viewportSizeF = viewportSizeInPt * devicePixelRatio;
const QSize viewportSize(std::ceil(viewportSizeF.width()), std::ceil(viewportSizeF.height()));
diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri
index 85b948db2..04c9eca89 100644
--- a/src/core/config/linux.pri
+++ b/src/core/config/linux.pri
@@ -19,11 +19,14 @@ gn_args += \
qtConfig(webengine-embedded-build) {
gn_args += is_desktop_linux=false
- gn_args += use_gold=false
-} else {
- !use_gold_linker: gn_args += use_gold=false
}
+use_gold_linker: gn_args += use_gold=true
+else: gn_args += use_gold=false
+
+use_lld_linker: gn_args += use_lld=true
+else: gn_args += use_lld=false
+
clang {
clang_full_path = $$which($${QMAKE_CXX})
# Remove the "/bin/clang++" part.
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index 846f3b908..7440771cb 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -76,6 +76,7 @@
#include "mojo/public/cpp/bindings/binding_set.h"
#include "printing/buildflags/buildflags.h"
#include "net/ssl/client_cert_identity.h"
+#include "net/ssl/client_cert_store.h"
#include "services/proxy_resolver/proxy_resolver_service.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/service.h"
@@ -91,7 +92,6 @@
#include "qtwebengine/grit/qt_webengine_resources.h"
-#include "client_cert_override_p.h"
#include "profile_adapter.h"
#include "browser_main_parts_qt.h"
#include "browser_message_filter_qt.h"
@@ -103,10 +103,12 @@
#include "media_capture_devices_dispatcher.h"
#include "net/network_delegate_qt.h"
#include "net/url_request_context_getter_qt.h"
+#include "platform_notification_service_qt.h"
#if QT_CONFIG(webengine_printing_and_pdf)
#include "printing/printing_message_filter_qt.h"
#endif
#include "profile_qt.h"
+#include "profile_io_data_qt.h"
#include "quota_permission_context_qt.h"
#include "renderer_host/user_resource_controller_host.h"
#include "service/service_qt.h"
@@ -161,7 +163,7 @@ public:
{
QString platform = qApp->platformName().toLower();
QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface();
- if (platform == QLatin1String("xcb")) {
+ if (platform == QLatin1String("xcb") || platform == QLatin1String("offscreen")) {
if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2)
m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext);
else
@@ -400,7 +402,7 @@ std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertSt
if (!resource_context)
return nullptr;
- return std::unique_ptr<net::ClientCertStore>(new net::ClientCertOverrideStore());
+ return ProfileIODataQt::FromResourceContext(resource_context)->CreateClientCertStore();
}
std::string ContentBrowserClientQt::GetApplicationLocale()
@@ -454,7 +456,7 @@ void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base:
void ContentBrowserClientQt::DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host)
{
browser_host->GetPpapiHost()->AddHostFactoryFilter(
- base::WrapUnique(new QtWebEngineCore::PepperHostFactoryQt(browser_host)));
+ std::make_unique<QtWebEngineCore::PepperHostFactoryQt>(browser_host));
}
#endif
@@ -463,6 +465,13 @@ content::DevToolsManagerDelegate* ContentBrowserClientQt::GetDevToolsManagerDele
return new DevToolsManagerDelegateQt;
}
+content::PlatformNotificationService *ContentBrowserClientQt::GetPlatformNotificationService()
+{
+ if (!m_platformNotificationService)
+ m_platformNotificationService = std::make_unique<PlatformNotificationServiceQt>();
+ return m_platformNotificationService.get();
+}
+
// This is a really complicated way of doing absolutely nothing, but Mojo demands it:
class ServiceDriver
: public blink::mojom::InsecureInputService
@@ -760,13 +769,19 @@ scoped_refptr<content::LoginDelegate> ContentBrowserClientQt::CreateLoginDelegat
return loginDelegate;
}
+bool ContentBrowserClientQt::ShouldIsolateErrorPage(bool in_main_frame)
+{
+ Q_UNUSED(in_main_frame);
+ return false;
+}
+
bool ContentBrowserClientQt::ShouldUseProcessPerSite(content::BrowserContext* browser_context, const GURL& effective_url)
{
#if BUILDFLAG(ENABLE_EXTENSIONS)
- return true;
-#else
- return ContentBrowserClient::ShouldUseProcessPerSite(browser_context, effective_url);
+ if (effective_url.SchemeIs(extensions::kExtensionScheme))
+ return true;
#endif
+ return ContentBrowserClient::ShouldUseProcessPerSite(browser_context, effective_url);
}
} // namespace QtWebEngineCore
diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h
index e90b687cc..403ff3a9d 100644
--- a/src/core/content_browser_client_qt.h
+++ b/src/core/content_browser_client_qt.h
@@ -108,6 +108,7 @@ public:
std::unique_ptr<content::ClientCertificateDelegate> delegate) override;
std::unique_ptr<net::ClientCertStore> CreateClientCertStore(content::ResourceContext *resource_context) override;
content::DevToolsManagerDelegate *GetDevToolsManagerDelegate() override;
+ content::PlatformNotificationService *GetPlatformNotificationService() override;
std::string GetApplicationLocale() override;
std::string GetAcceptLangs(content::BrowserContext* context) override;
@@ -175,6 +176,7 @@ public:
#if QT_CONFIG(webengine_geolocation)
std::unique_ptr<device::LocationProvider> OverrideSystemLocationProvider() override;
#endif
+ bool ShouldIsolateErrorPage(bool in_main_frame) override;
bool ShouldUseProcessPerSite(content::BrowserContext* browser_context, const GURL& effective_url) override;
#if defined(Q_OS_LINUX)
@@ -209,6 +211,7 @@ private:
BrowserMainPartsQt* m_browserMainParts;
std::unique_ptr<content::ResourceDispatcherHostDelegate> m_resourceDispatcherHostDelegate;
+ std::unique_ptr<content::PlatformNotificationService> m_platformNotificationService;
scoped_refptr<ShareGroupQtQuick> m_shareGroupQtQuick;
std::unique_ptr<service_manager::BinderRegistry> m_frameInterfaces;
std::unique_ptr<service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>> m_frameInterfacesParameterized;
diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp
index 9065174b8..9bfc8eede 100644
--- a/src/core/content_client_qt.cpp
+++ b/src/core/content_client_qt.cpp
@@ -288,9 +288,19 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path,
pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName);
#endif
#if defined(Q_OS_OSX)
- QDir potentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM");
+ QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Versions");
if (potentialWidevineDir.exists()) {
- QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed);
+ QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot,
+ QDir::Name | QDir::Reversed);
+ const QString library = QLatin1String("/Google Chrome Framework.framework/Versions/A/Libraries/"
+ "WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib");
+ for (const QFileInfo &info : widevineVersionDirs)
+ pluginPaths << info.absoluteFilePath() + library;
+ }
+
+ QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM");
+ if (oldPotentialWidevineDir.exists()) {
+ QFileInfoList widevineVersionDirs = oldPotentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed);
for (int i = 0; i < widevineVersionDirs.size(); ++i) {
QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath());
QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/" + QString::fromLatin1(kWidevineCdmFileName);
diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri
index 18cedc63e..f4cb8c9da 100644
--- a/src/core/core_chromium.pri
+++ b/src/core/core_chromium.pri
@@ -48,11 +48,11 @@ SOURCES = \
browser_message_filter_qt.cpp \
certificate_error_controller.cpp \
chromium_overrides.cpp \
- client_cert_override_key.cpp \
client_cert_select_controller.cpp \
clipboard_qt.cpp \
color_chooser_qt.cpp \
color_chooser_controller.cpp \
+ command_line_pref_store_qt.cpp \
common/qt_ipc_logging.cpp \
common/qt_messages.cpp \
common/user_script_data.cpp \
@@ -76,6 +76,8 @@ SOURCES = \
login_delegate_qt.cpp \
media_capture_devices_dispatcher.cpp \
native_web_keyboard_event_qt.cpp \
+ net/client_cert_override.cpp \
+ net/client_cert_store_data.cpp \
net/cookie_monster_delegate_qt.cpp \
net/custom_protocol_handler.cpp \
net/network_delegate_qt.cpp \
@@ -86,6 +88,7 @@ SOURCES = \
net/url_request_custom_job.cpp \
net/url_request_custom_job_delegate.cpp \
net/url_request_custom_job_proxy.cpp \
+ net/url_request_notification.cpp \
net/webui_controller_factory_qt.cpp \
ozone/gl_context_qt.cpp \
ozone/gl_ozone_egl_qt.cpp \
@@ -96,6 +99,7 @@ SOURCES = \
ozone/platform_window_qt.cpp \
ozone/surface_factory_qt.cpp \
permission_manager_qt.cpp \
+ platform_notification_service_qt.cpp \
process_main.cpp \
profile_adapter.cpp \
profile_adapter_client.cpp \
@@ -103,7 +107,6 @@ SOURCES = \
profile_io_data_qt.cpp \
quota_permission_context_qt.cpp \
quota_request_controller_impl.cpp \
- qwebengineclientcertificatestore.cpp \
register_protocol_handler_request_controller_impl.cpp \
render_view_context_menu_qt.cpp \
render_view_observer_host_qt.cpp \
@@ -121,6 +124,7 @@ SOURCES = \
touch_selection_controller_client_qt.cpp \
touch_selection_menu_controller.cpp \
type_conversion.cpp \
+ user_notification_controller.cpp \
user_script.cpp \
visited_links_manager_qt.cpp \
web_contents_adapter.cpp \
@@ -145,11 +149,9 @@ HEADERS = \
browser_message_filter_qt.h \
certificate_error_controller_p.h \
certificate_error_controller.h \
- chromium_overrides.h \
- client_cert_override_key_p.h \
- client_cert_override_p.h \
client_cert_select_controller.h \
clipboard_qt.h \
+ command_line_pref_store_qt.h \
color_chooser_qt.h \
color_chooser_controller_p.h \
color_chooser_controller.h \
@@ -178,6 +180,8 @@ HEADERS = \
locked_ptr.h \
login_delegate_qt.h \
media_capture_devices_dispatcher.h \
+ net/client_cert_override.h \
+ net/client_cert_store_data.h \
net/cookie_monster_delegate_qt.h \
net/custom_protocol_handler.h \
net/network_delegate_qt.h \
@@ -187,6 +191,7 @@ HEADERS = \
net/url_request_custom_job.h \
net/url_request_custom_job_delegate.h \
net/url_request_custom_job_proxy.h \
+ net/url_request_notification.h \
net/webui_controller_factory_qt.h \
ozone/gl_context_qt.h \
ozone/gl_ozone_egl_qt.h \
@@ -197,6 +202,7 @@ HEADERS = \
ozone/platform_window_qt.h \
ozone/surface_factory_qt.h \
permission_manager_qt.h \
+ platform_notification_service_qt.h \
process_main.h \
profile_adapter.h \
profile_adapter_client.h \
@@ -226,6 +232,7 @@ HEADERS = \
touch_selection_controller_client_qt.h \
touch_selection_menu_controller.h \
type_conversion.h \
+ user_notification_controller.h \
user_script.h \
visited_links_manager_qt.h \
web_contents_adapter.h \
diff --git a/src/core/core_common.pri b/src/core/core_common.pri
index 5f9f3c4f6..8375d89e5 100644
--- a/src/core/core_common.pri
+++ b/src/core/core_common.pri
@@ -13,3 +13,7 @@ CONFIG -= ltcg
# Chromium requires C++14
CONFIG += c++14
+
+#QTBUG-73216 ci has to be updated with latest yocto
+boot2qt: CONFIG -= use_gold_linker
+
diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp
index 398bde710..c8b75a893 100644
--- a/src/core/download_manager_delegate_qt.cpp
+++ b/src/core/download_manager_delegate_qt.cpp
@@ -79,7 +79,7 @@ DownloadManagerDelegateQt::~DownloadManagerDelegateQt()
void DownloadManagerDelegateQt::GetNextId(const content::DownloadIdCallback& callback)
{
- callback.Run(++m_currentId);
+ callback.Run(m_currentId);
}
download::DownloadItem *DownloadManagerDelegateQt::findDownloadById(quint32 downloadId)
@@ -124,6 +124,8 @@ void DownloadManagerDelegateQt::removeDownload(quint32 downloadId)
bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem* item,
const content::DownloadTargetCallback& callback)
{
+ m_currentId = item->GetId();
+
// Keep the forced file path if set, also as the temporary file, so the check for existence
// will already return that the file exists. Forced file paths seem to be only used for
// store downloads and other special downloads, so they might never end up here anyway.
@@ -184,6 +186,7 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem*
if (webContents)
adapterClient = static_cast<WebContentsDelegateQt *>(webContents->GetDelegate())->adapterClient();
+ Q_ASSERT(m_currentId == item->GetId());
ProfileAdapterClient::DownloadItemInfo info = {
item->GetId(),
toQt(item->GetURL()),
@@ -284,8 +287,9 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content
if (web_contents)
adapterClient = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate())->adapterClient();
+ // Chromium doesn't increase download ID when saving page.
ProfileAdapterClient::DownloadItemInfo info = {
- m_currentId + 1,
+ ++m_currentId,
toQt(web_contents->GetURL()),
download::DownloadItem::IN_PROGRESS,
0, /* totalBytes */
diff --git a/src/core/net/client_cert_override.cpp b/src/core/net/client_cert_override.cpp
new file mode 100644
index 000000000..caf6adad7
--- /dev/null
+++ b/src/core/net/client_cert_override.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "net/client_cert_override.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/task/post_task.h"
+#include "base/callback_forward.h"
+#include "net/ssl/client_cert_store.h"
+#include "net/ssl/ssl_cert_request_info.h"
+#include "net/ssl/ssl_private_key.h"
+#include "net/cert/x509_certificate.h"
+#include "third_party/boringssl/src/include/openssl/pem.h"
+#include "third_party/boringssl/src/include/openssl/err.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+
+#include "api/qwebengineclientcertificatestore.h"
+#include "net/client_cert_store_data.h"
+#include "profile_io_data_qt.h"
+
+#include <QtNetwork/qtnetworkglobal.h>
+
+#if defined(USE_NSS_CERTS)
+#include "net/ssl/client_cert_store_nss.h"
+#endif
+
+#if defined(OS_WIN)
+#include "net/ssl/client_cert_store_win.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "net/ssl/client_cert_store_mac.h"
+#endif
+
+namespace {
+
+class ClientCertIdentityOverride : public net::ClientCertIdentity
+{
+public:
+ ClientCertIdentityOverride(scoped_refptr<net::X509Certificate> cert, scoped_refptr<net::SSLPrivateKey> key)
+ : net::ClientCertIdentity(std::move(cert)), m_key(std::move(key)) {}
+ ~ClientCertIdentityOverride() override = default;
+
+ void AcquirePrivateKey(const base::Callback<void(scoped_refptr<net::SSLPrivateKey>)> &private_key_callback) override
+ {
+ private_key_callback.Run(m_key);
+ }
+
+#if defined(OS_MACOSX)
+ SecIdentityRef sec_identity_ref() const override
+ {
+ return nullptr;
+ }
+#endif
+
+private:
+ scoped_refptr<net::SSLPrivateKey> m_key;
+};
+
+} // namespace
+
+namespace QtWebEngineCore {
+
+ClientCertOverrideStore::ClientCertOverrideStore()
+ : ClientCertStore()
+ , m_nativeStore(createNativeStore())
+{
+}
+
+ClientCertOverrideStore::~ClientCertOverrideStore() = default;
+
+void ClientCertOverrideStore::GetClientCerts(const net::SSLCertRequestInfo &cert_request_info,
+ const ClientCertListCallback &callback)
+{
+#if QT_CONFIG(ssl)
+ QWebEngineClientCertificateStore *clientCertificateStore = QWebEngineClientCertificateStore::getInstance();
+ const auto &clientCertOverrideData = clientCertificateStore->d_ptr->addedCerts;
+ // Look for certificates in memory store
+ for (int i = 0; i < clientCertOverrideData.length(); i++) {
+ scoped_refptr<net::X509Certificate> cert = clientCertOverrideData[i]->certPtr;
+ if (cert != NULL && cert->IsIssuedByEncoded(cert_request_info.cert_authorities)) {
+ net::ClientCertIdentityList selected_identities;
+ selected_identities.push_back(std::make_unique<ClientCertIdentityOverride>(cert, clientCertOverrideData[i]->keyPtr));
+ callback.Run(std::move(selected_identities));
+ return;
+ }
+ }
+#endif // QT_CONFIG(ssl)
+
+ // Continue with native cert store if matching certificate is not found in memory
+ if (m_nativeStore) {
+ m_nativeStore->GetClientCerts(cert_request_info, callback);
+ return;
+ }
+
+ callback.Run(net::ClientCertIdentityList());
+ return;
+}
+
+// static
+std::unique_ptr<net::ClientCertStore> ClientCertOverrideStore::createNativeStore()
+{
+#if defined(USE_NSS_CERTS)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(net::ClientCertStoreNSS::PasswordDelegateFactory()));
+#elif defined(OS_WIN)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
+#elif defined(OS_MACOSX)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
+#else
+ return nullptr;
+#endif
+}
+} // namespace QtWebEngineCore
diff --git a/src/core/client_cert_override_p.h b/src/core/net/client_cert_override.h
index b222bf810..4f13c3116 100644
--- a/src/core/client_cert_override_p.h
+++ b/src/core/net/client_cert_override.h
@@ -46,17 +46,23 @@
namespace net {
class SSLCertRequestInfo;
-class ClientCertOverrideStore : public ClientCertStore
+} // namespace net
+
+namespace QtWebEngineCore {
+
+class ClientCertOverrideStore : public net::ClientCertStore
{
public:
ClientCertOverrideStore();
virtual ~ClientCertOverrideStore() override;
- void GetClientCerts(const SSLCertRequestInfo &cert_request_info,
+ void GetClientCerts(const net::SSLCertRequestInfo &cert_request_info,
const ClientCertListCallback &callback) override;
private:
- std::unique_ptr<net::ClientCertStore> getNativeStore();
+ static std::unique_ptr<net::ClientCertStore> createNativeStore();
+ std::unique_ptr<net::ClientCertStore> m_nativeStore;
};
-} // namespace net
+
+} // QtWebEngineCore
#endif
diff --git a/src/core/client_cert_override_key.cpp b/src/core/net/client_cert_store_data.cpp
index 99ddf7466..ae4deed1c 100644
--- a/src/core/client_cert_override_key.cpp
+++ b/src/core/net/client_cert_store_data.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -37,101 +37,115 @@
**
****************************************************************************/
-#ifndef CLIENT_CERT_OVERRIDE_KEY_H
-#define CLIENT_CERT_OVERRIDE_KEY_H
-
-#include "client_cert_override_key_p.h"
-
-#include "third_party/boringssl/src/include/openssl/ssl.h"
-#include "third_party/boringssl/src/include/openssl/digest.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-#include "third_party/boringssl/src/include/openssl/rsa.h"
-#include "third_party/boringssl/src/include/openssl/pem.h"
-
-#include <utility>
-#include <QByteArray>
+#include "net/client_cert_store_data.h"
+#if QT_CONFIG(ssl)
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "net/base/net_errors.h"
+#include "net/cert/x509_certificate.h"
#include "net/ssl/ssl_platform_key_util.h"
#include "net/ssl/ssl_private_key.h"
#include "net/ssl/threaded_ssl_private_key.h"
-namespace net {
+#include "third_party/boringssl/src/include/openssl/ssl.h"
+#include "third_party/boringssl/src/include/openssl/digest.h"
+#include "third_party/boringssl/src/include/openssl/evp.h"
+#include "third_party/boringssl/src/include/openssl/rsa.h"
+#include "third_party/boringssl/src/include/openssl/pem.h"
+
+#include "QtCore/qbytearray.h"
namespace {
-class SSLPlatformKeyOverride : public ThreadedSSLPrivateKey::Delegate {
+class SSLPlatformKeyOverride : public net::ThreadedSSLPrivateKey::Delegate {
public:
SSLPlatformKeyOverride(const QByteArray &sslKeyInBytes)
{
- mem_ = BIO_new_mem_buf(sslKeyInBytes, -1);
- key_ = PEM_read_bio_PrivateKey(mem_, NULL, 0, NULL);
+ m_mem = BIO_new_mem_buf(sslKeyInBytes, -1);
+ m_key = PEM_read_bio_PrivateKey(m_mem, nullptr, nullptr, nullptr);
}
- ~SSLPlatformKeyOverride() override {
- if (key_)
- EVP_PKEY_free(key_);
- if (mem_)
- BIO_free(mem_);
+ ~SSLPlatformKeyOverride() override
+ {
+ if (m_key)
+ EVP_PKEY_free(m_key);
+ if (m_mem)
+ BIO_free(m_mem);
}
- Error Sign(uint16_t algorithm,
- base::span<const uint8_t> input,
- std::vector<uint8_t>* signature) override {
+ net::Error Sign(uint16_t algorithm, base::span<const uint8_t> input, std::vector<uint8_t> *signature) override
+ {
bssl::ScopedEVP_MD_CTX ctx;
- EVP_PKEY_CTX* pctx;
+ EVP_PKEY_CTX *pctx;
if (!EVP_DigestSignInit(ctx.get(), &pctx,
SSL_get_signature_algorithm_digest(algorithm),
- nullptr, key_)) {
- return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ nullptr, m_key)) {
+ return net::ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
}
if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
!EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* hash length */)) {
- return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ return net::ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
}
}
size_t sig_len = 0;
if (!EVP_DigestSign(ctx.get(), NULL, &sig_len, input.data(), input.size()))
- return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
+ return net::ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
signature->resize(sig_len);
- if (!EVP_DigestSign(ctx.get(), signature->data(), &sig_len, input.data(),
- input.size())) {
- return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
- }
+ if (!EVP_DigestSign(ctx.get(), signature->data(), &sig_len, input.data(), input.size()))
+ return net::ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
signature->resize(sig_len);
- return OK;
+ return net::OK;
}
- std::vector<uint16_t> GetAlgorithmPreferences() override {
- return {
- SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA512,
- SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA256,
- };
+ std::vector<uint16_t> GetAlgorithmPreferences() override
+ {
+ return { SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA512
+ , SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA256 };
}
private:
- EVP_PKEY* key_;
- BIO * mem_;
+ EVP_PKEY *m_key;
+ BIO *m_mem;
DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyOverride);
};
-} // namespace
-
-scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(const QByteArray &sslKeyInBytes) {
+scoped_refptr<net::SSLPrivateKey> wrapOpenSSLPrivateKey(const QByteArray &sslKeyInBytes)
+{
if (sslKeyInBytes.isEmpty())
return nullptr;
- return base::MakeRefCounted<ThreadedSSLPrivateKey>(
+ return base::MakeRefCounted<net::ThreadedSSLPrivateKey>(
std::make_unique<SSLPlatformKeyOverride>(sslKeyInBytes),
- GetSSLPlatformKeyTaskRunner());
+ net::GetSSLPlatformKeyTaskRunner());
+}
+
+} // namespace
+
+namespace QtWebEngineCore {
+
+void ClientCertificateStoreData::add(const QSslCertificate &certificate, const QSslKey &privateKey)
+{
+ QByteArray sslKeyInBytes = privateKey.toPem();
+ QByteArray certInBytes = certificate.toDer();
+
+ Entry *data = new Entry;
+ data->keyPtr = wrapOpenSSLPrivateKey(sslKeyInBytes);
+ data->certPtr = net::X509Certificate::CreateFromBytes(certInBytes.data(), certInBytes.length());
+ data->key = privateKey;
+ data->certificate = certificate;
+ addedCerts.append(data);
+}
+
+ClientCertificateStoreData::~ClientCertificateStoreData()
+{
+ qDeleteAll(deletedCerts);
}
-} // namespace net
+} // namespace QtWebEngineCore
#endif
diff --git a/src/core/client_cert_override_key_p.h b/src/core/net/client_cert_store_data.h
index 7ac610be4..41dc1f8ec 100644
--- a/src/core/client_cert_override_key_p.h
+++ b/src/core/net/client_cert_store_data.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -37,16 +37,42 @@
**
****************************************************************************/
-#ifndef CLIENT_CERT_OVERRIDE_KEY_P_H
-#define CLIENT_CERT_OVERRIDE_KEY_P_H
+#ifndef CLIENT_CERT_STORE_DATA_H
+#define CLIENT_CERT_STORE_DATA_H
-#include "net/ssl/ssl_private_key.h"
+#include "qtwebenginecoreglobal.h"
+#include "qtnetworkglobal.h"
-#include <QByteArray>
+#if QT_CONFIG(ssl)
+#include "base/memory/ref_counted.h"
+
+#include <QtCore/qlist.h>
+#include <QtNetwork/qsslcertificate.h>
+#include <QtNetwork/qsslkey.h>
namespace net {
- class SSLPrivateKey;
- scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(const QByteArray &sslKeyInBytes);
-} // namespace net
+class SSLPrivateKey;
+class X509Certificate;
+}
+
+namespace QtWebEngineCore {
+
+struct ClientCertificateStoreData {
+ struct Entry {
+ QSslKey key;
+ QSslCertificate certificate;
+ scoped_refptr<net::X509Certificate> certPtr;
+ scoped_refptr<net::SSLPrivateKey> keyPtr;
+ };
+
+ ~ClientCertificateStoreData();
+ void add(const QSslCertificate &certificate, const QSslKey &privateKey);
+
+ QList<Entry*> addedCerts;
+ QList<Entry*> deletedCerts;
+};
+
+} // namespace QtWebEngineCore
#endif
+#endif // CLIENT_CERT_STORE_DATA_H
diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp
index 73f3ff818..3641cb845 100644
--- a/src/core/net/network_delegate_qt.cpp
+++ b/src/core/net/network_delegate_qt.cpp
@@ -58,6 +58,7 @@
#include "type_conversion.h"
#include "web_contents_adapter_client.h"
#include "web_contents_view_qt.h"
+#include "url_request_notification.h"
namespace QtWebEngineCore {
@@ -91,146 +92,11 @@ static QWebEngineUrlRequestInfo::ResourceType toQt(content::ResourceType resourc
return QWebEngineUrlRequestInfo::ResourceTypeUnknown;
}
-static content::ResourceType fromQt(QWebEngineUrlRequestInfo::ResourceType resourceType)
-{
- return static_cast<content::ResourceType>(resourceType);
-}
-
static QWebEngineUrlRequestInfo::NavigationType toQt(WebContentsAdapterClient::NavigationType navigationType)
{
return static_cast<QWebEngineUrlRequestInfo::NavigationType>(navigationType);
}
-// Notifies WebContentsAdapterClient of a new URLRequest.
-class URLRequestNotification {
-public:
- URLRequestNotification(net::URLRequest *request,
- bool isMainFrameRequest,
- GURL *newUrl,
- QWebEngineUrlRequestInfo &&requestInfo,
- content::ResourceRequestInfo::WebContentsGetter webContentsGetter,
- net::CompletionOnceCallback callback)
- : m_request(request)
- , m_isMainFrameRequest(isMainFrameRequest)
- , m_newUrl(newUrl)
- , m_originalUrl(requestInfo.requestUrl())
- , m_requestInfo(std::move(requestInfo))
- , m_webContentsGetter(webContentsGetter)
- , m_callback(std::move(callback))
- {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
- m_request->SetUserData(UserData::key, std::make_unique<UserData>(this));
-
- base::PostTaskWithTraits(
- FROM_HERE,
- {content::BrowserThread::UI},
- base::BindOnce(&URLRequestNotification::notify, base::Unretained(this)));
- }
-
-private:
- // Calls cancel() when the URLRequest is destroyed.
- class UserData : public base::SupportsUserData::Data {
- public:
- UserData(URLRequestNotification *ptr) : m_ptr(ptr) {}
- ~UserData() { m_ptr->cancel(); }
- static const char key[];
- private:
- URLRequestNotification *m_ptr;
- };
-
- void cancel()
- {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
- // May run concurrently with notify() but we only touch m_request here.
-
- m_request = nullptr;
- }
-
- void notify()
- {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- // May run concurrently with cancel() so no peeking at m_request here.
-
- int error = net::OK;
- content::WebContents *webContents = m_webContentsGetter.Run();
-
- if (webContents) {
- WebContentsAdapterClient *client =
- WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client();
-
- client->interceptRequest(m_requestInfo);
- if (m_requestInfo.changed()) {
- error = m_requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
- // We handle the rest of the changes later when we are back in I/O thread
- }
-
- // Only do navigationRequested on MAIN_FRAME and SUB_FRAME resources
- if (error == net::OK && content::IsResourceTypeFrame(fromQt(m_requestInfo.resourceType()))) {
- int navigationRequestAction = WebContentsAdapterClient::AcceptRequest;
- client->navigationRequested(m_requestInfo.navigationType(),
- m_requestInfo.requestUrl(),
- navigationRequestAction,
- m_isMainFrameRequest);
- error = net::ERR_FAILED;
- switch (static_cast<WebContentsAdapterClient::NavigationRequestAction>(navigationRequestAction)) {
- case WebContentsAdapterClient::AcceptRequest:
- error = net::OK;
- break;
- case WebContentsAdapterClient::IgnoreRequest:
- error = net::ERR_ABORTED;
- break;
- }
- DCHECK(error != net::ERR_FAILED);
- }
- }
-
- // Run the callback on the IO thread.
- base::PostTaskWithTraits(
- FROM_HERE,
- {content::BrowserThread::IO},
- base::BindOnce(&URLRequestNotification::complete, base::Unretained(this), error));
- }
-
- void complete(int error)
- {
- DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
-
- if (m_request) {
- if (m_requestInfo.changed()) {
- if (m_originalUrl != m_requestInfo.d_ptr->url)
- *m_newUrl = toGurl(m_requestInfo.d_ptr->url);
-
- if (!m_requestInfo.d_ptr->extraHeaders.isEmpty()) {
- auto end = m_requestInfo.d_ptr->extraHeaders.constEnd();
- for (auto header = m_requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header)
- m_request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true);
- }
- }
-
- if (m_request->status().status() != net::URLRequestStatus::CANCELED)
- std::move(m_callback).Run(error);
- m_request->RemoveUserData(UserData::key);
- }
-
- delete this;
- }
-
- ~URLRequestNotification() {}
-
- net::URLRequest *m_request;
- bool m_isMainFrameRequest;
- GURL *m_newUrl;
- const QUrl m_originalUrl;
- QWebEngineUrlRequestInfo m_requestInfo;
- content::ResourceRequestInfo::WebContentsGetter m_webContentsGetter;
- net::CompletionOnceCallback m_callback;
-};
-
-const char URLRequestNotification::UserData::key[] = "QtWebEngineCore::URLRequestNotification";
-
NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data)
: m_profileIOData(data)
{
@@ -265,33 +131,41 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
QByteArray::fromStdString(request->method()));
QWebEngineUrlRequestInfo requestInfo(infoPrivate);
- if (QWebEngineUrlRequestInterceptor* interceptor = m_profileIOData->acquireInterceptor()) {
- interceptor->interceptRequest(requestInfo);
- m_profileIOData->releaseInterceptor();
- if (requestInfo.changed()) {
- int result = infoPrivate->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
+ // Deprecated =begin
+ // quick peek if deprecated
+ QWebEngineUrlRequestInterceptor* profileInterceptor = m_profileIOData->requestInterceptor();
+ if (profileInterceptor && profileInterceptor->property("deprecated").toBool()) {
+ profileInterceptor = nullptr;
+ if (QWebEngineUrlRequestInterceptor* interceptor = m_profileIOData->acquireInterceptor()) {
+ interceptor->interceptRequest(requestInfo);
+ m_profileIOData->releaseInterceptor();
+ if (requestInfo.changed()) {
+ int result = infoPrivate->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
+
+ if (qUrl != infoPrivate->url)
+ *newUrl = toGurl(infoPrivate->url);
+
+ if (!infoPrivate->extraHeaders.isEmpty()) {
+ auto end = infoPrivate->extraHeaders.constEnd();
+ for (auto header = infoPrivate->extraHeaders.constBegin(); header != end; ++header)
+ request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true);
+ }
- if (qUrl != infoPrivate->url)
- *newUrl = toGurl(infoPrivate->url);
+ if (result != net::OK)
+ return result;
- if (!infoPrivate->extraHeaders.isEmpty()) {
- auto end = infoPrivate->extraHeaders.constEnd();
- for (auto header = infoPrivate->extraHeaders.constBegin(); header != end; ++header)
- request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true);
+ requestInfo.resetChanged();
}
-
- if (result != net::OK)
- return result;
-
- requestInfo.resetChanged();
+ } else {
+ m_profileIOData->releaseInterceptor();
}
- } else
- m_profileIOData->releaseInterceptor();
+ }
+ // Deprecated =cut
if (!resourceInfo)
return net::OK;
- if (!m_profileIOData->hasPageInterceptors() && !content::IsResourceTypeFrame(resourceType))
+ if (!m_profileIOData->hasPageInterceptors() && !profileInterceptor && !content::IsResourceTypeFrame(resourceType))
return net::OK;
auto webContentsGetter = resourceInfo->GetWebContentsGetterForRequest();
@@ -301,7 +175,8 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, net::Complet
newUrl,
std::move(requestInfo),
webContentsGetter,
- std::move(callback)
+ std::move(callback),
+ profileInterceptor ? m_profileIOData->profileAdapter() : nullptr
);
// We'll run the callback after we notified the UI thread.
diff --git a/src/core/net/proxy_config_service_qt.cpp b/src/core/net/proxy_config_service_qt.cpp
index 13b969281..ff8ab20aa 100644
--- a/src/core/net/proxy_config_service_qt.cpp
+++ b/src/core/net/proxy_config_service_qt.cpp
@@ -47,6 +47,7 @@
#include "base/bind.h"
#include "content/public/browser/browser_thread.h"
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
using content::BrowserThread;
@@ -68,10 +69,13 @@ net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qt
}
}
-ProxyConfigServiceQt::ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService)
+ProxyConfigServiceQt::ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService,
+ const net::ProxyConfigWithAnnotation& initialConfig, ProxyPrefs::ConfigState initialState)
: m_baseService(baseService.release()),
m_usesSystemConfiguration(false),
- m_registeredObserver(false)
+ m_registeredObserver(false),
+ m_prefConfig(initialConfig),
+ m_perfState(initialState)
{
}
@@ -100,8 +104,10 @@ net::ProxyConfigService::ConfigAvailability ProxyConfigServiceQt::GetLatestProxy
ConfigAvailability systemAvailability = net::ProxyConfigService::CONFIG_UNSET;
if (m_baseService.get())
systemAvailability = m_baseService->GetLatestProxyConfig(&systemConfig);
- *config = systemConfig;
- // make sure to get updates via OnProxyConfigChanged
+ ProxyPrefs::ConfigState configState;
+ systemAvailability = PrefProxyConfigTrackerImpl::GetEffectiveProxyConfig(
+ m_perfState, m_prefConfig, systemAvailability, systemConfig,
+ false, &configState, config);
RegisterObserver();
return systemAvailability;
}
diff --git a/src/core/net/proxy_config_service_qt.h b/src/core/net/proxy_config_service_qt.h
index 961927b89..09e88d445 100644
--- a/src/core/net/proxy_config_service_qt.h
+++ b/src/core/net/proxy_config_service_qt.h
@@ -43,8 +43,10 @@
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
+#include "net/proxy_resolution/proxy_config.h"
#include "net/proxy_resolution/proxy_config_service.h"
#include "net/proxy_resolution/proxy_config_with_annotation.h"
+#include "components/proxy_config/proxy_prefs.h"
#include <QNetworkProxy>
@@ -55,7 +57,9 @@ public:
static net::ProxyServer fromQNetworkProxy(const QNetworkProxy &);
- explicit ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService);
+ explicit ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService,
+ const net::ProxyConfigWithAnnotation& initialConfig,
+ ProxyPrefs::ConfigState initialState);
~ProxyConfigServiceQt() override;
// ProxyConfigService implementation:
@@ -86,6 +90,10 @@ private:
// Indicates whether the base service registration is done.
bool m_registeredObserver;
+ // Configuration as defined by prefs.
+ net::ProxyConfigWithAnnotation m_prefConfig;
+ ProxyPrefs::ConfigState m_perfState;
+
DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceQt);
};
diff --git a/src/core/net/url_request_notification.cpp b/src/core/net/url_request_notification.cpp
new file mode 100644
index 000000000..6da661cff
--- /dev/null
+++ b/src/core/net/url_request_notification.cpp
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "url_request_notification.h"
+
+#include "base/supports_user_data.h"
+#include "base/task/post_task.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/url_request/url_request.h"
+#include "web_contents_adapter_client.h"
+#include "web_contents_view_qt.h"
+#include "profile_io_data_qt.h"
+#include "qwebengineurlrequestinfo_p.h"
+#include "type_conversion.h"
+
+namespace QtWebEngineCore {
+
+// Calls cancel() when the URLRequest is destroyed.
+class UserData : public base::SupportsUserData::Data {
+public:
+ UserData(URLRequestNotification *ptr) : m_ptr(ptr) {}
+ ~UserData() { m_ptr->cancel(); }
+ static const char key[];
+private:
+ URLRequestNotification *m_ptr;
+};
+
+const char UserData::key[] = "QtWebEngineCore::URLRequestNotification";
+
+static content::ResourceType fromQt(QWebEngineUrlRequestInfo::ResourceType resourceType)
+{
+ return static_cast<content::ResourceType>(resourceType);
+}
+
+URLRequestNotification::URLRequestNotification(net::URLRequest *request,
+ bool isMainFrameRequest,
+ GURL *newUrl,
+ QWebEngineUrlRequestInfo &&requestInfo,
+ content::ResourceRequestInfo::WebContentsGetter webContentsGetter,
+ net::CompletionOnceCallback callback,
+ QPointer<ProfileAdapter> adapter)
+ : m_request(request)
+ , m_isMainFrameRequest(isMainFrameRequest)
+ , m_newUrl(newUrl)
+ , m_originalUrl(requestInfo.requestUrl())
+ , m_requestInfo(std::move(requestInfo))
+ , m_webContentsGetter(webContentsGetter)
+ , m_callback(std::move(callback))
+ , m_profileAdapter(adapter)
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ m_request->SetUserData(UserData::key, std::make_unique<UserData>(this));
+
+ base::PostTaskWithTraits(
+ FROM_HERE,
+ {content::BrowserThread::UI},
+ base::BindOnce(&URLRequestNotification::notify, base::Unretained(this)));
+}
+
+
+void URLRequestNotification::notify()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // May run concurrently with cancel() so no peeking at m_request here.
+
+ int result = net::OK;
+ content::WebContents *webContents = m_webContentsGetter.Run();
+
+ if (webContents) {
+
+ if (m_profileAdapter) {
+ QWebEngineUrlRequestInterceptor* interceptor = m_profileAdapter->requestInterceptor();
+ interceptor->interceptRequest(m_requestInfo);
+ }
+
+ WebContentsAdapterClient *client =
+ WebContentsViewQt::from(static_cast<content::WebContentsImpl*>(webContents)->GetView())->client();
+
+ if (!m_requestInfo.changed()) {
+ client->interceptRequest(m_requestInfo);
+ }
+
+ if (m_requestInfo.changed()) {
+ result = m_requestInfo.d_ptr->shouldBlockRequest ? net::ERR_BLOCKED_BY_CLIENT : net::OK;
+ // We handle the rest of the changes later when we are back in I/O thread
+ }
+
+ // Only do navigationRequested on MAIN_FRAME and SUB_FRAME resources
+ if (result == net::OK && content::IsResourceTypeFrame(fromQt(m_requestInfo.resourceType()))) {
+ int navigationRequestAction = WebContentsAdapterClient::AcceptRequest;
+ client->navigationRequested(m_requestInfo.navigationType(),
+ m_requestInfo.requestUrl(),
+ navigationRequestAction,
+ m_isMainFrameRequest);
+ result = net::ERR_FAILED;
+ switch (static_cast<WebContentsAdapterClient::NavigationRequestAction>(navigationRequestAction)) {
+ case WebContentsAdapterClient::AcceptRequest:
+ result = net::OK;
+ break;
+ case WebContentsAdapterClient::IgnoreRequest:
+ result = net::ERR_ABORTED;
+ break;
+ }
+ DCHECK(result != net::ERR_FAILED);
+ }
+ }
+
+ // Run the callback on the IO thread.
+ base::PostTaskWithTraits(
+ FROM_HERE,
+ {content::BrowserThread::IO},
+ base::BindOnce(&URLRequestNotification::complete, base::Unretained(this), result));
+}
+
+void URLRequestNotification::cancel()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ // May run concurrently with notify() but we only touch m_request here.
+
+ m_request = nullptr;
+}
+
+void URLRequestNotification::complete(int error)
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+
+ if (m_request) {
+ if (m_requestInfo.changed()) {
+ if (m_originalUrl != m_requestInfo.d_ptr->url)
+ *m_newUrl = toGurl(m_requestInfo.d_ptr->url);
+
+ if (!m_requestInfo.d_ptr->extraHeaders.isEmpty()) {
+ auto end = m_requestInfo.d_ptr->extraHeaders.constEnd();
+ for (auto header = m_requestInfo.d_ptr->extraHeaders.constBegin(); header != end; ++header)
+ m_request->SetExtraRequestHeaderByName(header.key().toStdString(), header.value().toStdString(), /* overwrite */ true);
+ }
+ }
+
+ if (m_request->status().status() != net::URLRequestStatus::CANCELED)
+ std::move(m_callback).Run(error);
+ m_request->RemoveUserData(UserData::key);
+ }
+
+ delete this;
+}
+
+}
diff --git a/src/core/net/url_request_notification.h b/src/core/net/url_request_notification.h
new file mode 100644
index 000000000..1d9acf12f
--- /dev/null
+++ b/src/core/net/url_request_notification.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef URL_REQUEST_NOTIFIACTION_H
+#define URL_REQUEST_NOTIFIACTION_H
+
+#include "content/public/browser/resource_request_info.h"
+#include "net/base/completion_once_callback.h"
+#include "qwebengineurlrequestinfo.h"
+#include <QPointer>
+
+class GURL;
+
+namespace net {
+class URLRequest;
+}
+
+namespace QtWebEngineCore {
+
+class ProfileAdapter;
+class ProfileIoDataQt;
+
+// Notifies WebContentsAdapterClient of a new URLRequest.
+class URLRequestNotification {
+public:
+ URLRequestNotification(net::URLRequest *request,
+ bool isMainFrameRequest,
+ GURL *newUrl,
+ QWebEngineUrlRequestInfo &&requestInfo,
+ content::ResourceRequestInfo::WebContentsGetter webContentsGetter,
+ net::CompletionOnceCallback callback,
+ QPointer<ProfileAdapter> adapter);
+ ~URLRequestNotification() = default;
+ void cancel();
+ void notify();
+ void complete(int error);
+
+private:
+ net::URLRequest *m_request; //used only by io thread
+ bool m_isMainFrameRequest;
+ GURL *m_newUrl;
+ const QUrl m_originalUrl;
+ QWebEngineUrlRequestInfo m_requestInfo;
+ content::ResourceRequestInfo::WebContentsGetter m_webContentsGetter;
+ net::CompletionOnceCallback m_callback;
+ QPointer<ProfileAdapter> m_profileAdapter;
+};
+}
+#endif
diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp
index 7e913817e..c4a075544 100644
--- a/src/core/ozone/gl_context_qt.cpp
+++ b/src/core/ozone/gl_context_qt.cpp
@@ -130,9 +130,10 @@ void* GLContextHelper::getEGLDisplay()
void* GLContextHelper::getXDisplay()
{
- if (QGuiApplication::platformName() != QLatin1String("xcb"))
- return nullptr;
- return qApp->platformNativeInterface()->nativeResourceForScreen(QByteArrayLiteral("display"), qApp->primaryScreen());
+ QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface();
+ if (pni)
+ return pni->nativeResourceForScreen(QByteArrayLiteral("display"), qApp->primaryScreen());
+ return nullptr;
}
void* GLContextHelper::getNativeDisplay()
diff --git a/src/core/ozone/gl_surface_glx_qt.cpp b/src/core/ozone/gl_surface_glx_qt.cpp
index eebefa59b..4faa08091 100644
--- a/src/core/ozone/gl_surface_glx_qt.cpp
+++ b/src/core/ozone/gl_surface_glx_qt.cpp
@@ -173,7 +173,7 @@ bool GLSurfaceGLXQt::Initialize(GLSurfaceFormat format)
GLX_PBUFFER_HEIGHT, m_size.height(),
GLX_LARGEST_PBUFFER, x11::False,
GLX_PRESERVED_CONTENTS, x11::False,
- GLX_NONE
+ NULL
};
m_surfaceBuffer = glXCreatePbuffer(display, static_cast<GLXFBConfig>(g_config), pbuffer_attributes);
diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp
index b6d055e27..2a7311187 100644
--- a/src/core/permission_manager_qt.cpp
+++ b/src/core/permission_manager_qt.cpp
@@ -48,6 +48,7 @@
#include "type_conversion.h"
#include "web_contents_delegate_qt.h"
+#include "web_engine_settings.h"
namespace QtWebEngineCore {
@@ -60,8 +61,9 @@ ProfileAdapter::PermissionType toQt(content::PermissionType type)
return ProfileAdapter::AudioCapturePermission;
case content::PermissionType::VIDEO_CAPTURE:
return ProfileAdapter::VideoCapturePermission;
- case content::PermissionType::FLASH:
case content::PermissionType::NOTIFICATIONS:
+ return ProfileAdapter::NotificationPermission;
+ case content::PermissionType::FLASH:
case content::PermissionType::MIDI_SYSEX:
case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
case content::PermissionType::MIDI:
@@ -69,8 +71,11 @@ ProfileAdapter::PermissionType toQt(content::PermissionType type)
case content::PermissionType::BACKGROUND_SYNC:
case content::PermissionType::SENSORS:
case content::PermissionType::ACCESSIBILITY_EVENTS:
+ break;
case content::PermissionType::CLIPBOARD_READ:
+ return ProfileAdapter::ClipboardRead;
case content::PermissionType::CLIPBOARD_WRITE:
+ return ProfileAdapter::ClipboardWrite;
case content::PermissionType::PAYMENT_HANDLER:
case content::PermissionType::BACKGROUND_FETCH:
case content::PermissionType::NUM:
@@ -154,19 +159,28 @@ int PermissionManagerQt::RequestPermission(content::PermissionType permission,
bool /*user_gesture*/,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
{
- int request_id = ++m_requestIdCount;
+ WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
+ content::WebContents::FromRenderFrameHost(frameHost)->GetDelegate());
+ Q_ASSERT(contentsDelegate);
+
ProfileAdapter::PermissionType permissionType = toQt(permission);
if (permissionType == ProfileAdapter::UnsupportedPermission) {
callback.Run(blink::mojom::PermissionStatus::DENIED);
return content::PermissionController::kNoPendingOperation;
+ } else if (permissionType == ProfileAdapter::ClipboardRead) {
+ WebEngineSettings *settings = contentsDelegate->webEngineSettings();
+ if (settings->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard)
+ && settings->testAttribute(WebEngineSettings::JavascriptCanPaste))
+ callback.Run(blink::mojom::PermissionStatus::GRANTED);
+ else
+ callback.Run(blink::mojom::PermissionStatus::DENIED);
+ return content::PermissionController::kNoPendingOperation;
}
// Audio and video-capture should not come this way currently
Q_ASSERT(permissionType != ProfileAdapter::AudioCapturePermission
&& permissionType != ProfileAdapter::VideoCapturePermission);
- content::WebContents *webContents = frameHost->GetRenderViewHost()->GetDelegate()->GetAsWebContents();
- WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate());
- Q_ASSERT(contentsDelegate);
+ int request_id = ++m_requestIdCount;
RequestOrSubscription request = {
permissionType,
toQt(requesting_origin),
@@ -175,6 +189,9 @@ int PermissionManagerQt::RequestPermission(content::PermissionType permission,
m_requests.insert(request_id, request);
if (permissionType == ProfileAdapter::GeolocationPermission)
contentsDelegate->requestGeolocationPermission(request.origin);
+ else if (permissionType == ProfileAdapter::NotificationPermission)
+ contentsDelegate->requestUserNotificationPermission(request.origin);
+
return request_id;
}
@@ -184,6 +201,10 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio
bool /*user_gesture*/,
const base::Callback<void(const std::vector<blink::mojom::PermissionStatus>&)>& callback)
{
+ WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
+ content::WebContents::FromRenderFrameHost(frameHost)->GetDelegate());
+ Q_ASSERT(contentsDelegate);
+
bool answerable = true;
std::vector<blink::mojom::PermissionStatus> result;
result.reserve(permissions.size());
@@ -191,7 +212,14 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio
const ProfileAdapter::PermissionType permissionType = toQt(permission);
if (permissionType == ProfileAdapter::UnsupportedPermission)
result.push_back(blink::mojom::PermissionStatus::DENIED);
- else {
+ else if (permissionType == ProfileAdapter::ClipboardRead) {
+ WebEngineSettings *settings = contentsDelegate->webEngineSettings();
+ if (settings->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard)
+ && settings->testAttribute(WebEngineSettings::JavascriptCanPaste))
+ result.push_back(blink::mojom::PermissionStatus::GRANTED);
+ else
+ result.push_back(blink::mojom::PermissionStatus::DENIED);
+ } else {
answerable = false;
break;
}
@@ -202,9 +230,6 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio
}
int request_id = ++m_requestIdCount;
- content::WebContents *webContents = frameHost->GetRenderViewHost()->GetDelegate()->GetAsWebContents();
- WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate());
- Q_ASSERT(contentsDelegate);
MultiRequest request = {
permissions,
toQt(requesting_origin),
@@ -215,6 +240,8 @@ int PermissionManagerQt::RequestPermissions(const std::vector<content::Permissio
const ProfileAdapter::PermissionType permissionType = toQt(permission);
if (permissionType == ProfileAdapter::GeolocationPermission)
contentsDelegate->requestGeolocationPermission(request.origin);
+ else if (permissionType == ProfileAdapter::NotificationPermission)
+ contentsDelegate->requestUserNotificationPermission(request.origin);
}
return request_id;
}
@@ -241,6 +268,18 @@ blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForFrame(
content::RenderFrameHost *render_frame_host,
const GURL &requesting_origin)
{
+ if (permission == content::PermissionType::CLIPBOARD_READ ||
+ permission == content::PermissionType::CLIPBOARD_WRITE) {
+ WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(
+ content::WebContents::FromRenderFrameHost(render_frame_host)->GetDelegate());
+ if (!delegate->webEngineSettings()->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard))
+ return blink::mojom::PermissionStatus::DENIED;
+ if (permission == content::PermissionType::CLIPBOARD_READ &&
+ !delegate->webEngineSettings()->testAttribute(WebEngineSettings::JavascriptCanPaste))
+ return blink::mojom::PermissionStatus::DENIED;
+ return blink::mojom::PermissionStatus::GRANTED;
+ }
+
return GetPermissionStatus(
permission,
requesting_origin,
diff --git a/src/core/platform_notification_service_qt.cpp b/src/core/platform_notification_service_qt.cpp
new file mode 100644
index 000000000..dff3aed61
--- /dev/null
+++ b/src/core/platform_notification_service_qt.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "platform_notification_service_qt.h"
+
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/permission_type.h"
+#include "content/public/browser/notification_event_dispatcher.h"
+#include "ui/message_center/public/cpp/notification_delegate.h"
+
+#include "profile_adapter.h"
+#include "profile_adapter_client.h"
+#include "profile_qt.h"
+#include "user_notification_controller.h"
+#include "resource_context_qt.h"
+#include "type_conversion.h"
+
+#include <QSharedPointer>
+
+namespace QtWebEngineCore {
+
+struct NonPersistentNotificationDelegate : UserNotificationController::Delegate {
+ NonPersistentNotificationDelegate(const std::string &id) : notification_id(id) { }
+
+ virtual void shown() override {
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (auto inst = content::NotificationEventDispatcher::GetInstance())
+ inst->DispatchNonPersistentShowEvent(notification_id);
+ }
+
+ virtual void clicked() override {
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (auto inst = content::NotificationEventDispatcher::GetInstance())
+ inst->DispatchNonPersistentClickEvent(notification_id, base::DoNothing());
+ }
+
+ virtual void closed(bool /*by_user*/) override {
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (auto inst = content::NotificationEventDispatcher::GetInstance())
+ inst->DispatchNonPersistentCloseEvent(notification_id, base::DoNothing());
+ }
+
+ const std::string notification_id;
+};
+
+struct PersistentNotificationDelegate : UserNotificationController::Delegate {
+ PersistentNotificationDelegate(content::BrowserContext *context, const std::string &id, const GURL &origin)
+ : browser_context(context), notification_id(id), origin(origin) { }
+
+ virtual void shown() override { }
+
+ virtual void clicked() override {
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (auto inst = content::NotificationEventDispatcher::GetInstance())
+ inst->DispatchNotificationClickEvent(browser_context, notification_id, origin, base::nullopt, base::nullopt, base::DoNothing());
+ }
+
+ virtual void closed(bool by_user) override {
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ if (auto inst = content::NotificationEventDispatcher::GetInstance())
+ inst->DispatchNotificationCloseEvent(browser_context, notification_id, origin, by_user, base::DoNothing());
+ }
+
+ content::BrowserContext *browser_context;
+ const std::string notification_id;
+ const GURL origin;
+};
+
+
+PlatformNotificationServiceQt::PlatformNotificationServiceQt() {}
+
+PlatformNotificationServiceQt::~PlatformNotificationServiceQt() {}
+
+void PlatformNotificationServiceQt::DisplayNotification(
+ content::BrowserContext *browser_context,
+ const std::string &notification_id,
+ const GURL &origin,
+ const blink::PlatformNotificationData &notificationData,
+ const blink::NotificationResources &notificationResources)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ ProfileQt *profile = static_cast<ProfileQt*>(browser_context);
+
+ auto delegate = new NonPersistentNotificationDelegate(notification_id);
+ QSharedPointer<UserNotificationController> controller(
+ new UserNotificationController(notificationData, notificationResources, origin, delegate));
+
+ profile->profileAdapter()->ephemeralNotifications().insert(QByteArray::fromStdString(notification_id), controller);
+
+ const QList<ProfileAdapterClient *> clients = profile->profileAdapter()->clients();
+ for (ProfileAdapterClient *client : clients)
+ client->showNotification(controller);
+}
+
+void PlatformNotificationServiceQt::DisplayPersistentNotification(
+ content::BrowserContext *browser_context,
+ const std::string &notification_id,
+ const GURL &service_worker_origin,
+ const GURL &origin,
+ const blink::PlatformNotificationData &notificationData,
+ const blink::NotificationResources &notificationResources)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ ProfileQt * profile = static_cast<ProfileQt*>(browser_context);
+
+ auto delegate = new PersistentNotificationDelegate(profile, notification_id, service_worker_origin);
+ QSharedPointer<UserNotificationController> controller(
+ new UserNotificationController(notificationData, notificationResources, service_worker_origin, delegate));
+
+ profile->profileAdapter()->persistentNotifications().insert(QByteArray::fromStdString(notification_id), controller);
+ const QList<ProfileAdapterClient *> clients = profile->profileAdapter()->clients();
+ for (ProfileAdapterClient *client : clients)
+ client->showNotification(controller);
+}
+
+void PlatformNotificationServiceQt::CloseNotification(
+ content::BrowserContext *browser_context,
+ const std::string &notification_id)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ ProfileQt *profile = static_cast<ProfileQt*>(browser_context);
+
+ QSharedPointer<UserNotificationController> notificationController =
+ profile->profileAdapter()->ephemeralNotifications().take(QByteArray::fromStdString(notification_id)).lock();
+ if (notificationController)
+ notificationController->closeNotification();
+}
+
+void PlatformNotificationServiceQt::ClosePersistentNotification(
+ content::BrowserContext *browser_context,
+ const std::string &notification_id)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ ProfileQt *profile = static_cast<ProfileQt*>(browser_context);
+
+ QSharedPointer<UserNotificationController> notificationController =
+ profile->profileAdapter()->persistentNotifications().take(QByteArray::fromStdString(notification_id));
+ if (notificationController)
+ notificationController->closeNotification();
+}
+
+void PlatformNotificationServiceQt::GetDisplayedNotifications(
+ content::BrowserContext *browser_context,
+ const DisplayedNotificationsCallback &callback)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ ProfileQt *profile = static_cast<ProfileQt *>(browser_context);
+
+ std::unique_ptr<std::set<std::string>> movableStdStringSet = std::make_unique<std::set<std::string>>();
+ auto it = profile->profileAdapter()->persistentNotifications().constBegin();
+ const auto end = profile->profileAdapter()->persistentNotifications().constEnd();
+ while (it != end) {
+ if (it.value()->isShown())
+ movableStdStringSet->insert(it.key().toStdString());
+ ++it;
+ }
+
+ callback.Run(std::move(movableStdStringSet), true /* supports_synchronization */);
+}
+
+int64_t PlatformNotificationServiceQt::ReadNextPersistentNotificationId(content::BrowserContext *browser_context)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ auto prefs = static_cast<ProfileQt *>(browser_context)->GetPrefs();
+ int64_t nextId = prefs->GetInteger(prefs::kNotificationNextPersistentId) + 1;
+ prefs->SetInt64(prefs::kNotificationNextPersistentId, nextId);
+ return nextId;
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/platform_notification_service_qt.h b/src/core/platform_notification_service_qt.h
new file mode 100644
index 000000000..66cee9ed0
--- /dev/null
+++ b/src/core/platform_notification_service_qt.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PLATFORM_NOTIFICATION_SERVICE_QT_H
+#define PLATFORM_NOTIFICATION_SERVICE_QT_H
+
+#include "content/public/browser/platform_notification_service.h"
+
+namespace QtWebEngineCore {
+
+class PlatformNotificationServiceQt : public content::PlatformNotificationService {
+public:
+ PlatformNotificationServiceQt();
+ ~PlatformNotificationServiceQt() override;
+
+ // Displays the notification described in |notification_data| to the user. A
+ // closure through which the notification can be closed will be stored in the
+ // |cancel_callback| argument. This method must be called on the UI thread.
+ void DisplayNotification(content::BrowserContext* browser_context,
+ const std::string& notification_id,
+ const GURL& origin,
+ const blink::PlatformNotificationData& notificationData,
+ const blink::NotificationResources& notificationResources) override;
+
+ // Displays the persistent notification described in |notification_data| to
+ // the user. This method must be called on the UI thread.
+ void DisplayPersistentNotification(content::BrowserContext* browser_context,
+ const std::string& notification_id,
+ const GURL& service_worker_origin,
+ const GURL& origin,
+ const blink::PlatformNotificationData& notification_data,
+ const blink::NotificationResources& notification_resources) override;
+
+ // Closes the notification identified by |notification_id|.
+ // This method must be called on the UI thread.
+ void CloseNotification(content::BrowserContext* browser_context, const std::string& notification_id) override;
+
+ // Closes the persistent notification identified by |persistent_notification_id|.
+ // This method must be called on the UI thread.
+ void ClosePersistentNotification(content::BrowserContext* browser_context, const std::string& notification_id) override;
+
+ // Retrieves the ids of all currently displaying notifications and
+ // posts |callback| with the result.
+ void GetDisplayedNotifications(content::BrowserContext* browser_context, const DisplayedNotificationsCallback& callback) override;
+
+ // Reads the value of the next persistent notification ID from the profile and
+ // increments the value, as it is called once per notification write.
+ virtual int64_t ReadNextPersistentNotificationId(content::BrowserContext* browser_context) override;
+
+ // Records a given notification to UKM.
+ virtual void RecordNotificationUkmEvent(content::BrowserContext*, const content::NotificationDatabaseData&) override { }
+};
+
+} // namespace QtWebEngineCore
+
+#endif // PLATFORM_NOTIFICATION_SERVICE_QT_H
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 48a6906e9..8ddeb5b8f 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -83,12 +83,12 @@ namespace QtWebEngineCore {
ProfileAdapter::ProfileAdapter(const QString &storageName):
m_name(storageName)
, m_offTheRecord(storageName.isEmpty())
+ , m_downloadPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))
, m_httpCacheType(DiskHttpCache)
, m_persistentCookiesPolicy(AllowPersistentCookies)
, m_visitedLinksPolicy(TrackVisitedLinksOnDisk)
, m_httpCacheMaxSize(0)
, m_pageRequestInterceptors(0)
- , m_downloadPath(QStandardPaths::writableLocation(QStandardPaths::DownloadLocation))
{
WebEngineContext::current()->addProfileAdapter(this);
// creation of profile requires webengine context
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index 3b1b9bc91..482835010 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -69,8 +69,9 @@ QT_FORWARD_DECLARE_CLASS(QObject)
namespace QtWebEngineCore {
-class ProfileAdapterClient;
+class UserNotificationController;
class DownloadManagerDelegateQt;
+class ProfileAdapterClient;
class ProfileQt;
class UserResourceControllerHost;
class VisitedLinksManagerQt;
@@ -153,10 +154,11 @@ public:
enum PermissionType {
UnsupportedPermission = 0,
GeolocationPermission = 1,
-// Reserved:
-// NotificationPermission = 2,
+ NotificationPermission = 2,
AudioCapturePermission = 3,
VideoCapturePermission = 4,
+ ClipboardRead = 5,
+ ClipboardWrite = 6,
};
HttpCacheType httpCacheType() const;
@@ -198,6 +200,11 @@ public:
void removePageRequestInterceptor();
bool hasPageRequestInterceptor() const { return m_pageRequestInterceptors > 0; }
+ QHash<QByteArray, QWeakPointer<UserNotificationController>> &ephemeralNotifications()
+ { return m_ephemeralNotifications; }
+ QHash<QByteArray, QSharedPointer<UserNotificationController>> &persistentNotifications()
+ { return m_persistentNotifications; }
+
private:
void updateCustomUrlSchemeHandlers();
void resetVisitedLinksManager();
@@ -222,6 +229,9 @@ private:
PersistentCookiesPolicy m_persistentCookiesPolicy;
VisitedLinksPolicy m_visitedLinksPolicy;
QHash<QByteArray, QPointer<QWebEngineUrlSchemeHandler>> m_customUrlSchemeHandlers;
+ QHash<QByteArray, QWeakPointer<UserNotificationController>> m_ephemeralNotifications;
+ QHash<QByteArray, QSharedPointer<UserNotificationController>> m_persistentNotifications;
+
QList<ProfileAdapterClient*> m_clients;
int m_httpCacheMaxSize;
int m_pageRequestInterceptors;
diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h
index 4711f8bcf..0309200b4 100644
--- a/src/core/profile_adapter_client.h
+++ b/src/core/profile_adapter_client.h
@@ -52,12 +52,14 @@
#define PROFILE_ADAPTER_CLIENT_H
#include "qtwebenginecoreglobal_p.h"
+#include <QSharedPointer>
#include <QString>
#include <QUrl>
namespace QtWebEngineCore {
class WebContentsAdapterClient;
+class UserNotificationController;
class QWEBENGINECORE_PRIVATE_EXPORT ProfileAdapterClient
{
@@ -143,6 +145,8 @@ public:
virtual void downloadRequested(DownloadItemInfo &info) = 0;
virtual void downloadUpdated(const DownloadItemInfo &info) = 0;
virtual void useForGlobalCertificateVerificationChanged() {}
+ virtual void showNotification(QSharedPointer<UserNotificationController> &) { }
+
static QString downloadInterruptReasonToString(DownloadInterruptReason reason);
};
diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp
index 83886ca54..01a4e98aa 100644
--- a/src/core/profile_io_data_qt.cpp
+++ b/src/core/profile_io_data_qt.cpp
@@ -49,6 +49,7 @@
#include "content/public/common/content_features.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h"
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_log_verifier.h"
#include "net/cert/ct_policy_enforcer.h"
@@ -77,6 +78,7 @@
#include "services/file/user_id_map.h"
#include "services/network/proxy_service_mojo.h"
+#include "net/client_cert_override.h"
#include "net/cookie_monster_delegate_qt.h"
#include "net/custom_protocol_handler.h"
#include "net/network_delegate_qt.h"
@@ -187,6 +189,9 @@ ProfileIODataQt::~ProfileIODataQt()
#endif
}
+ if (m_urlRequestContext && m_urlRequestContext->proxy_resolution_service())
+ m_urlRequestContext->proxy_resolution_service()->OnShutdown();
+
m_resourceContext.reset();
if (m_cookieDelegate)
m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted
@@ -194,6 +199,11 @@ ProfileIODataQt::~ProfileIODataQt()
delete m_proxyConfigService.fetchAndStoreAcquire(0);
}
+QPointer<ProfileAdapter> ProfileIODataQt::profileAdapter()
+{
+ return m_profileAdapter;
+}
+
void ProfileIODataQt::shutdownOnUIThread()
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -233,10 +243,10 @@ void ProfileIODataQt::initializeOnIOThread()
// this binds factory to io thread
m_weakPtr = m_weakPtrFactory.GetWeakPtr();
QMutexLocker lock(&m_mutex);
- m_initialized = true;
generateAllStorage();
generateJobFactory();
setGlobalCertificateVerification();
+ m_initialized = true;
}
void ProfileIODataQt::initializeOnUIThread()
@@ -251,6 +261,7 @@ void ProfileIODataQt::initializeOnUIThread()
protocolHandlerRegistry->CreateJobInterceptorFactory();
m_cookieDelegate = new CookieMonsterDelegateQt();
m_cookieDelegate->setClient(m_profile->profileAdapter()->cookieStore());
+ createProxyConfig();
}
void ProfileIODataQt::cancelAllUrlRequests()
@@ -286,11 +297,12 @@ void ProfileIODataQt::generateStorage()
// We must stop all requests before deleting their backends.
if (m_storage) {
- m_cookieDelegate->setCookieMonster(0);
- m_storage->set_cookie_store(0);
+ m_urlRequestContext->proxy_resolution_service()->OnShutdown();
+ m_cookieDelegate->setCookieMonster(nullptr);
+ m_storage->set_cookie_store(nullptr);
cancelAllUrlRequests();
// we need to get rid of dangling pointer due to coming storage deletion
- m_urlRequestContext->set_http_transaction_factory(0);
+ m_urlRequestContext->set_http_transaction_factory(nullptr);
m_httpNetworkSession.reset();
m_transportSecurityPersister.reset();
}
@@ -310,29 +322,23 @@ void ProfileIODataQt::generateStorage()
m_storage->set_cert_verifier(std::move(cert_verifier));
std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier());
-// FIXME:
-// ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs());
+ std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs;
+ for (const auto &ct_log : certificate_transparency::GetKnownLogs()) {
+ scoped_refptr<const net::CTLogVerifier> log_verifier =
+ net::CTLogVerifier::Create(std::string(ct_log.log_key, ct_log.log_key_length),
+ ct_log.log_name,
+ ct_log.log_dns_domain);
+ if (!log_verifier)
+ continue;
+ ct_logs.push_back(std::move(log_verifier));
+ }
+ ct_verifier->AddLogs(ct_logs);
m_storage->set_cert_transparency_verifier(std::move(ct_verifier));
m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::DefaultCTPolicyEnforcer()));
-
- std::unique_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
-
- // The System Proxy Resolver has issues on Windows with unconfigured network cards,
- // which is why we want to use the v8 one
- if (!m_dhcpPacFileFetcherFactory)
- m_dhcpPacFileFetcherFactory.reset(new net::DhcpPacFileFetcherFactory);
-
- proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface));
- m_storage->set_proxy_resolution_service(network::CreateProxyResolutionServiceUsingMojoFactory(
- std::move(proxyResolver),
- std::unique_ptr<net::ProxyConfigService>(proxyConfigService),
- net::PacFileFetcherImpl::CreateWithFileUrlSupport(m_urlRequestContext.get()),
- m_dhcpPacFileFetcherFactory->Create(m_urlRequestContext.get()),
- host_resolver.get(),
- nullptr /* NetLog */,
- m_networkDelegate.get()));
-
+ m_storage->set_host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
m_storage->set_ssl_config_service(std::make_unique<net::SSLConfigServiceDefaults>());
+ m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault(
+ m_urlRequestContext->host_resolver()));
m_storage->set_transport_security_state(std::make_unique<net::TransportSecurityState>());
if (!m_dataPath.isEmpty()) {
@@ -348,20 +354,23 @@ void ProfileIODataQt::generateStorage()
background_task_runner);
};
- if (!m_httpAuthPreferences)
- m_httpAuthPreferences.reset(new net::HttpAuthPreferences());
-
- m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault(
- host_resolver.get(),
- m_httpAuthPreferences.get()
-#if (defined(OS_POSIX) && !defined(OS_ANDROID)) || defined(OS_FUCHSIA)
- , std::string() /* gssapi library name */
-#endif
- ));
m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>(
new net::HttpServerPropertiesImpl));
- // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|.
- m_storage->set_host_resolver(std::move(host_resolver));
+
+ // The System Proxy Resolver has issues on Windows with unconfigured network cards,
+ // which is why we want to use the v8 one
+ if (!m_dhcpPacFileFetcherFactory)
+ m_dhcpPacFileFetcherFactory.reset(new net::DhcpPacFileFetcherFactory);
+
+ proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface));
+ m_storage->set_proxy_resolution_service(network::CreateProxyResolutionServiceUsingMojoFactory(
+ std::move(proxyResolver),
+ std::unique_ptr<net::ProxyConfigService>(proxyConfigService),
+ net::PacFileFetcherImpl::CreateWithFileUrlSupport(m_urlRequestContext.get()),
+ m_dhcpPacFileFetcherFactory->Create(m_urlRequestContext.get()),
+ m_urlRequestContext->host_resolver(),
+ nullptr /* NetLog */,
+ m_urlRequestContext->network_delegate()));
}
@@ -369,10 +378,8 @@ void ProfileIODataQt::generateCookieStore()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_urlRequestContext);
- Q_ASSERT(m_storage);
QMutexLocker lock(&m_mutex);
- m_updateCookieStore = false;
scoped_refptr<net::SQLiteChannelIDStore> channel_id_db;
if (!m_channelIdPath.isEmpty() && m_persistentCookiesPolicy != ProfileAdapter::NoPersistentCookies) {
@@ -386,11 +393,6 @@ void ProfileIODataQt::generateCookieStore()
base::WrapUnique(new net::ChannelIDService(
new net::DefaultChannelIDStore(channel_id_db.get()))));
- // Unset it first to get a chance to destroy and flush the old cookie store before
- // opening a new on possibly the same file.
- m_cookieDelegate->setCookieMonster(0);
- m_storage->set_cookie_store(0);
-
std::unique_ptr<net::CookieStore> cookieStore;
switch (m_persistentCookiesPolicy) {
case ProfileAdapter::NoPersistentCookies:
@@ -430,11 +432,6 @@ void ProfileIODataQt::generateCookieStore()
const std::vector<std::string> cookieableSchemes(kCookieableSchemes,
kCookieableSchemes + arraysize(kCookieableSchemes));
cookieMonster->SetCookieableSchemes(cookieableSchemes);
-
- if (!m_updateAllStorage && m_updateHttpCache) {
- // HttpCache needs to be regenerated when we generate a new channel id service
- generateHttpCache();
- }
}
void ProfileIODataQt::generateUserAgent()
@@ -444,8 +441,6 @@ void ProfileIODataQt::generateUserAgent()
Q_ASSERT(m_storage);
QMutexLocker lock(&m_mutex);
- m_updateUserAgent = false;
-
m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>(
new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(),
m_httpUserAgent.toStdString())));
@@ -458,10 +453,6 @@ void ProfileIODataQt::generateHttpCache()
Q_ASSERT(m_storage);
QMutexLocker lock(&m_mutex);
- m_updateHttpCache = false;
-
- if (m_updateCookieStore)
- generateCookieStore();
net::HttpCache::DefaultBackend* main_backend = 0;
switch (m_httpCacheType) {
@@ -628,6 +619,38 @@ void ProfileIODataQt::setFullConfiguration()
m_dataPath = m_profileAdapter->dataPath();
}
+void ProfileIODataQt::requestStorageGeneration() {
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ if (m_initialized && !m_updateAllStorage) {
+ m_updateAllStorage = true;
+ createProxyConfig();
+ base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
+ base::BindOnce(&ProfileIODataQt::generateAllStorage, m_weakPtr));
+ }
+}
+
+// TODO(miklocek): mojofy ProxyConfigServiceQt
+void ProfileIODataQt::createProxyConfig()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ // We must create the proxy config service on the UI loop on Linux because it
+ // must synchronously run on the glib message loop. This will be passed to
+ // the URLRequestContextStorage on the IO thread in GetURLRequestContext().
+ Q_ASSERT(m_proxyConfigService == 0);
+ net::ProxyConfigWithAnnotation initialConfig;
+ ProxyPrefs::ConfigState initialConfigState = PrefProxyConfigTrackerImpl::ReadPrefConfig(
+ m_profileAdapter->profile()->GetPrefs(), &initialConfig);
+ m_proxyConfigService =
+ new ProxyConfigServiceQt(
+ net::ProxyResolutionService::CreateSystemProxyConfigService(
+ base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})),
+ initialConfig, initialConfigState);
+ //pass interface to io thread
+ m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithStrongBinding().PassInterface();
+}
+
void ProfileIODataQt::updateStorageSettings()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -640,23 +663,7 @@ void ProfileIODataQt::updateStorageSettings()
file::ForgetServiceUserIdUserDirAssociation(userId);
file::AssociateServiceUserIdWithUserDir(userId, toFilePath(m_profileAdapter->dataPath()));
}
-
- if (!m_updateAllStorage) {
- m_updateAllStorage = true;
- // We must create the proxy config service on the UI loop on Linux because it
- // must synchronously run on the glib message loop. This will be passed to
- // the URLRequestContextStorage on the IO thread in GetURLRequestContext().
- Q_ASSERT(m_proxyConfigService == 0);
- m_proxyConfigService =
- new ProxyConfigServiceQt(
- net::ProxyResolutionService::CreateSystemProxyConfigService(
- base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})));
- //pass interface to io thread
- m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithStrongBinding().PassInterface();
- if (m_initialized)
- base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ProfileIODataQt::generateAllStorage, m_weakPtr));
- }
+ requestStorageGeneration();
}
void ProfileIODataQt::updateCookieStore()
@@ -666,13 +673,7 @@ void ProfileIODataQt::updateCookieStore()
m_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy();
m_cookiesPath = m_profileAdapter->cookiesPath();
m_channelIdPath = m_profileAdapter->channelIdPath();
-
- if (m_initialized && !m_updateAllStorage && !m_updateCookieStore) {
- m_updateCookieStore = true;
- m_updateHttpCache = true;
- base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ProfileIODataQt::generateCookieStore, m_weakPtr));
- }
+ requestStorageGeneration();
}
void ProfileIODataQt::updateUserAgent()
@@ -681,12 +682,7 @@ void ProfileIODataQt::updateUserAgent()
QMutexLocker lock(&m_mutex);
m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage();
m_httpUserAgent = m_profileAdapter->httpUserAgent();
-
- if (m_initialized && !m_updateAllStorage && !m_updateUserAgent) {
- m_updateUserAgent = true;
- base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ProfileIODataQt::generateUserAgent, m_weakPtr));
- }
+ requestStorageGeneration();
}
void ProfileIODataQt::updateHttpCache()
@@ -705,12 +701,7 @@ void ProfileIODataQt::updateHttpCache()
content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB);
}
-
- if (m_initialized && !m_updateAllStorage && !m_updateHttpCache) {
- m_updateHttpCache = true;
- base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ProfileIODataQt::generateHttpCache, m_weakPtr));
- }
+ requestStorageGeneration();
}
void ProfileIODataQt::updateJobFactory()
@@ -742,6 +733,11 @@ QWebEngineUrlRequestInterceptor *ProfileIODataQt::acquireInterceptor()
return m_requestInterceptor;
}
+QWebEngineUrlRequestInterceptor *ProfileIODataQt::requestInterceptor()
+{
+ return m_requestInterceptor;
+}
+
bool ProfileIODataQt::hasPageInterceptors()
{
// used in NetworkDelegateQt::OnBeforeURLRequest
@@ -775,4 +771,15 @@ void ProfileIODataQt::updateUsedForGlobalCertificateVerification()
base::BindOnce(&ProfileIODataQt::setGlobalCertificateVerification, m_weakPtr));
}
+std::unique_ptr<net::ClientCertStore> ProfileIODataQt::CreateClientCertStore()
+{
+ return std::unique_ptr<net::ClientCertStore>(new ClientCertOverrideStore());
+}
+
+// static
+ProfileIODataQt *ProfileIODataQt::FromResourceContext(content::ResourceContext *resource_context)
+{
+ return static_cast<ResourceContextQt *>(resource_context)->m_io_data;
+}
+
} // namespace QtWebEngineCore
diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h
index 23497c476..b983b3a99 100644
--- a/src/core/profile_io_data_qt.h
+++ b/src/core/profile_io_data_qt.h
@@ -51,6 +51,7 @@
#include <QtCore/QMutex>
namespace net {
+class ClientCertStore;
class DhcpPacFileFetcherFactory;
class HttpAuthPreferences;
class HttpNetworkSession;
@@ -80,6 +81,7 @@ public:
ProfileIODataQt(ProfileQt *profile); // runs on ui thread
virtual ~ProfileIODataQt();
+ QPointer<ProfileAdapter> profileAdapter();
content::ResourceContext *resourceContext();
net::URLRequestContext *urlRequestContext();
#if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -105,6 +107,7 @@ public:
// Used in NetworkDelegateQt::OnBeforeURLRequest.
QWebEngineUrlRequestInterceptor *acquireInterceptor();
void releaseInterceptor();
+ QWebEngineUrlRequestInterceptor *requestInterceptor();
void setRequestContextData(content::ProtocolHandlerMap *protocolHandlers,
content::URLRequestInterceptorScopedVector request_interceptors);
@@ -115,9 +118,13 @@ public:
void updateHttpCache(); // runs on ui thread
void updateJobFactory(); // runs on ui thread
void updateRequestInterceptor(); // runs on ui thread
+ void requestStorageGeneration(); //runs on ui thread
+ void createProxyConfig(); //runs on ui thread
void updateUsedForGlobalCertificateVerification(); // runs on ui thread
bool hasPageInterceptors();
+ std::unique_ptr<net::ClientCertStore> CreateClientCertStore();
+ static ProfileIODataQt *FromResourceContext(content::ResourceContext *resource_context);
private:
ProfileQt *m_profile;
std::unique_ptr<net::URLRequestContextStorage> m_storage;
@@ -152,10 +159,7 @@ private:
int m_httpCacheMaxSize = 0;
bool m_initialized = false;
bool m_updateAllStorage = false;
- bool m_updateCookieStore = false;
- bool m_updateHttpCache = false;
bool m_updateJobFactory = false;
- bool m_updateUserAgent = false;
bool m_ignoreCertificateErrors = false;
bool m_useForGlobalCertificateVerification = false;
bool m_hasPageInterceptors = false;
diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp
index 68e933d85..3bfbcd3a2 100644
--- a/src/core/profile_qt.cpp
+++ b/src/core/profile_qt.cpp
@@ -41,6 +41,7 @@
#include "profile_adapter.h"
#include "browsing_data_remover_delegate_qt.h"
+#include "command_line_pref_store_qt.h"
#include "download_manager_delegate_qt.h"
#include "net/ssl_host_state_delegate_qt.h"
#include "net/url_request_context_getter_qt.h"
@@ -48,6 +49,7 @@
#include "qtwebenginecoreglobal_p.h"
#include "type_conversion.h"
#include "web_engine_library_info.h"
+#include "web_engine_context.h"
#include "base/time/time.h"
#include "content/public/browser/browser_thread.h"
@@ -62,9 +64,10 @@
#include "components/prefs/pref_service_factory.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/user_prefs/user_prefs.h"
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
+#include "chrome/common/pref_names.h"
#if QT_CONFIG(webengine_spellchecker)
#include "chrome/browser/spellchecker/spellcheck_service.h"
-#include "chrome/common/pref_names.h"
#include "components/spellcheck/browser/pref_names.h"
#endif
@@ -89,8 +92,10 @@ ProfileQt::ProfileQt(ProfileAdapter *profileAdapter)
{
PrefServiceFactory factory;
factory.set_user_prefs(new InMemoryPrefStore);
+ factory.set_command_line_prefs(base::MakeRefCounted<CommandLinePrefStoreQt>(
+ WebEngineContext::commandLine()));
PrefRegistrySimple *registry = new PrefRegistrySimple();
-
+ PrefProxyConfigTrackerImpl::RegisterPrefs(registry);
#if QT_CONFIG(webengine_spellchecker)
// Initial spellcheck settings
registry->RegisterStringPref(prefs::kAcceptLanguages, std::string());
@@ -101,6 +106,7 @@ ProfileQt::ProfileQt(ProfileAdapter *profileAdapter)
registry->RegisterBooleanPref(spellcheck::prefs::kSpellCheckUseSpellingService, false);
#endif // QT_CONFIG(webengine_spellchecker)
registry->RegisterBooleanPref(prefs::kShowInternalAccessibilityTree, false);
+ registry->RegisterIntegerPref(prefs::kNotificationNextPersistentId, 10000);
#if BUILDFLAG(ENABLE_EXTENSIONS)
registry->RegisterDictionaryPref(extensions::pref_names::kExtensions);
diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni
index b7f10833a..7c0ca763e 100644
--- a/src/core/qtwebengine.gni
+++ b/src/core/qtwebengine.gni
@@ -27,6 +27,7 @@ deps = [
"//components/web_cache/browser",
"//components/web_cache/renderer",
"//components/spellcheck:buildflags",
+ "//components/proxy_config",
"//content/public/app:browser",
"//content",
"//media:media_buildflags",
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 0217bed59..9791c8c46 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -40,7 +40,6 @@
#include "render_widget_host_view_qt.h"
#include "browser_accessibility_manager_qt.h"
-#include "chromium_overrides.h"
#include "compositor/compositor.h"
#include "qtwebenginecoreglobal_p.h"
#include "render_widget_host_view_qt_delegate.h"
@@ -67,7 +66,6 @@
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/gesture_detection/gesture_provider_config_helper.h"
#include "ui/events/gesture_detection/motion_event.h"
-#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/touch_selection/touch_selection_controller.h"
@@ -248,6 +246,22 @@ private:
int index;
};
+static content::ScreenInfo screenInfoFromQScreen(QScreen *screen)
+{
+ content::ScreenInfo r;
+ if (screen) {
+ r.device_scale_factor = screen->devicePixelRatio();
+ r.depth_per_component = 8;
+ r.depth = screen->depth();
+ r.is_monochrome = (r.depth == 1);
+ r.rect = toGfx(screen->geometry());
+ r.available_rect = toGfx(screen->availableGeometry());
+ } else {
+ r.device_scale_factor = qGuiApp->devicePixelRatio();
+ }
+ return r;
+}
+
RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget)
: content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget)
, m_gestureProvider(QtGestureProviderConfig(), this)
@@ -264,7 +278,6 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget
, m_cursorPosition(0)
, m_emptyPreviousSelection(true)
, m_wheelAckPending(false)
- , m_pendingResize(false)
, m_mouseWheelPhaseHandler(this)
// This frame-sink id is based on what RenderWidgetHostViewChildFrame does:
, m_frameSinkId(base::checked_cast<uint32_t>(widget->GetProcess()->GetID()),
@@ -303,6 +316,7 @@ RenderWidgetHostViewQt::~RenderWidgetHostViewQt()
void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate)
{
m_delegate.reset(delegate);
+ visualPropertiesChanged();
}
void RenderWidgetHostViewQt::setAdapterClient(WebContentsAdapterClient *adapterClient)
@@ -329,30 +343,16 @@ void RenderWidgetHostViewQt::InitAsFullscreen(content::RenderWidgetHostView*)
{
}
-void RenderWidgetHostViewQt::SetSize(const gfx::Size& size)
+void RenderWidgetHostViewQt::SetSize(const gfx::Size &sizeInDips)
{
- int width = size.width();
- int height = size.height();
-
- m_delegate->resize(width,height);
+ m_delegate->resize(sizeInDips.width(), sizeInDips.height());
}
-void RenderWidgetHostViewQt::SetBounds(const gfx::Rect& screenRect)
+void RenderWidgetHostViewQt::SetBounds(const gfx::Rect &windowRectInDips)
{
- // This is called when webkit has sent us a Move message.
- if (IsPopup())
- m_delegate->move(toQt(screenRect.origin()));
- SetSize(screenRect.size());
-}
-
-gfx::Size RenderWidgetHostViewQt::GetCompositorViewportPixelSize() const
-{
- if (!m_delegate || !m_delegate->window() || !m_delegate->window()->screen())
- return gfx::Size();
-
- const QScreen* screen = m_delegate->window()->screen();
- gfx::SizeF size = toGfx(m_delegate->screenRect().size());
- return gfx::ToCeiledSize(gfx::ScaleSize(size, screen->devicePixelRatio()));
+ DCHECK(IsPopup());
+ m_delegate->move(toQt(windowRectInDips.origin()));
+ m_delegate->resize(windowRectInDips.width(), windowRectInDips.height());
}
gfx::NativeView RenderWidgetHostViewQt::GetNativeView() const
@@ -431,10 +431,7 @@ bool RenderWidgetHostViewQt::IsShowing()
// Retrieve the bounds of the View, in screen coordinates.
gfx::Rect RenderWidgetHostViewQt::GetViewBounds() const
{
- QRectF p = m_delegate->contentsRect();
- gfx::Point p1(floor(p.x()), floor(p.y()));
- gfx::Point p2(ceil(p.right()), ceil(p.bottom()));
- return gfx::BoundingRect(p1, p2);
+ return m_viewRectInDips;
}
void RenderWidgetHostViewQt::UpdateBackgroundColor()
@@ -588,15 +585,13 @@ void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor)
}
#if defined(USE_AURA)
if (auraType != ui::CursorType::kNull) {
- QWindow *window = m_delegate->window();
- qreal windowDpr = window ? window->devicePixelRatio() : 1.0f;
int resourceId;
gfx::Point hotspot;
// GetCursorDataFor only knows hotspots for 1x and 2x cursor images, in physical pixels.
- qreal hotspotDpr = windowDpr <= 1.0f ? 1.0f : 2.0f;
+ qreal hotspotDpr = m_screenInfo.device_scale_factor <= 1.0f ? 1.0f : 2.0f;
if (ui::GetCursorDataFor(ui::CursorSize::kNormal, auraType, hotspotDpr, &resourceId, &hotspot)) {
if (const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId)) {
- QImage imageQt = toQImage(imageSkia->GetRepresentation(windowDpr));
+ QImage imageQt = toQImage(imageSkia->GetRepresentation(m_screenInfo.device_scale_factor));
// Convert hotspot coordinates into device-independent pixels.
qreal hotX = hotspot.x() / hotspotDpr;
@@ -693,28 +688,16 @@ void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &lo
m_adapterClient->updateScrollPosition(toQt(m_lastScrollOffset));
if (contentsSizeChanged)
m_adapterClient->updateContentsSize(toQt(m_lastContentsSize));
-
- if (m_pendingResize && host()) {
- if (host()->SynchronizeVisualProperties())
- m_pendingResize = false;
- }
}
void RenderWidgetHostViewQt::GetScreenInfo(content::ScreenInfo *results) const
{
- QWindow *window = m_delegate->window();
- if (!window)
- return;
- GetScreenInfoFromNativeWindow(window, results);
+ *results = m_screenInfo;
}
gfx::Rect RenderWidgetHostViewQt::GetBoundsInRootWindow()
{
- if (!m_delegate->window())
- return gfx::Rect();
-
- QRect r = m_delegate->window()->frameGeometry();
- return gfx::Rect(r.x(), r.y(), r.width(), r.height());
+ return m_windowRectInDips;
}
void RenderWidgetHostViewQt::ClearCompositorFrame()
@@ -922,15 +905,7 @@ viz::ScopedSurfaceIdAllocator RenderWidgetHostViewQt::DidUpdateVisualProperties(
void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata)
{
- if (metadata.local_surface_id)
- m_localSurfaceIdAllocator.UpdateFromChild(*metadata.local_surface_id);
-
- m_localSurfaceIdAllocator.GenerateId();
- host()->SendScreenRects();
- if (m_pendingResize) {
- if (host()->SynchronizeVisualProperties())
- m_pendingResize = false;
- }
+ synchronizeVisualProperties(metadata.local_surface_id);
}
QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode)
@@ -938,13 +913,6 @@ QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode)
return m_compositor->updatePaintNode(oldNode, m_delegate.get());
}
-void RenderWidgetHostViewQt::notifyResize()
-{
- m_pendingResize = true;
- if (host()->SynchronizeVisualProperties())
- m_pendingResize = false;
-}
-
void RenderWidgetHostViewQt::notifyShown()
{
host()->WasShown(false);
@@ -955,17 +923,26 @@ void RenderWidgetHostViewQt::notifyHidden()
host()->WasHidden();
}
-void RenderWidgetHostViewQt::windowBoundsChanged()
+void RenderWidgetHostViewQt::visualPropertiesChanged()
{
- host()->SendScreenRects();
- if (m_delegate && m_delegate->window())
- host()->NotifyScreenInfoChanged();
-}
+ if (!m_delegate)
+ return;
-void RenderWidgetHostViewQt::windowChanged()
-{
- if (m_delegate && m_delegate->window())
- host()->NotifyScreenInfoChanged();
+ gfx::Rect oldViewRect = m_viewRectInDips;
+ m_viewRectInDips = toGfx(m_delegate->viewGeometry().toAlignedRect());
+
+ gfx::Rect oldWindowRect = m_windowRectInDips;
+ QWindow *window = m_delegate->window();
+ m_windowRectInDips = window ? toGfx(window->frameGeometry()) : gfx::Rect();
+
+ content::ScreenInfo oldScreenInfo = m_screenInfo;
+ m_screenInfo = screenInfoFromQScreen(window ? window->screen() : nullptr);
+
+ if (m_viewRectInDips != oldViewRect || m_windowRectInDips != oldWindowRect)
+ host()->SendScreenRects();
+
+ if (m_viewRectInDips.size() != oldViewRect.size() || m_screenInfo != oldScreenInfo)
+ synchronizeVisualProperties(base::nullopt);
}
bool RenderWidgetHostViewQt::forwardEvent(QEvent *event)
@@ -1749,4 +1726,14 @@ void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation()
}
}
+void RenderWidgetHostViewQt::synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceId> &childSurfaceId)
+{
+ if (childSurfaceId)
+ m_localSurfaceIdAllocator.UpdateFromChild(*childSurfaceId);
+ else
+ m_localSurfaceIdAllocator.GenerateId();
+
+ host()->SynchronizeVisualProperties();
+}
+
} // namespace QtWebEngineCore
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index f7bd82f03..70b4f509e 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -124,7 +124,6 @@ public:
void InitAsFullscreen(content::RenderWidgetHostView*) override;
void SetSize(const gfx::Size& size) override;
void SetBounds(const gfx::Rect&) override;
- gfx::Size GetCompositorViewportPixelSize() const override;
gfx::NativeView GetNativeView() const override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
void Focus() override;
@@ -176,11 +175,9 @@ public:
// Overridden from RenderWidgetHostViewQtDelegateClient.
QSGNode *updatePaintNode(QSGNode *) override;
- void notifyResize() override;
void notifyShown() override;
void notifyHidden() override;
- void windowBoundsChanged() override;
- void windowChanged() override;
+ void visualPropertiesChanged() override;
bool forwardEvent(QEvent *) override;
QVariant inputMethodQuery(Qt::InputMethodQuery query) override;
void closePopup() override;
@@ -234,13 +231,20 @@ private:
void processMotionEvent(const ui::MotionEvent &motionEvent);
void clearPreviousTouchMotionState();
QList<QTouchEvent::TouchPoint> mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints);
- void updateNeedsBeginFramesInternal();
bool IsPopup() const;
void selectionChanged();
content::RenderFrameHost *getFocusedFrameHost();
+ void synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceId> &childSurfaceId);
+
+ // Geometry of the view in screen DIPs.
+ gfx::Rect m_viewRectInDips;
+ // Geometry of the window, including frame, in screen DIPs.
+ gfx::Rect m_windowRectInDips;
+ content::ScreenInfo m_screenInfo;
+
ui::FilteredGestureProvider m_gestureProvider;
base::TimeDelta m_eventsToNowDelta;
bool m_sendMotionActionDown;
@@ -274,7 +278,6 @@ private:
bool m_imeHasHiddenTextCapability;
bool m_wheelAckPending;
- bool m_pendingResize;
QList<blink::WebMouseWheelEvent> m_pendingWheelEvents;
content::MouseWheelPhaseHandler m_mouseWheelPhaseHandler;
viz::FrameSinkId m_frameSinkId;
diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h
index 5ce595502..e2c98360d 100644
--- a/src/core/render_widget_host_view_qt_delegate.h
+++ b/src/core/render_widget_host_view_qt_delegate.h
@@ -78,11 +78,9 @@ class QWEBENGINECORE_PRIVATE_EXPORT RenderWidgetHostViewQtDelegateClient {
public:
virtual ~RenderWidgetHostViewQtDelegateClient() { }
virtual QSGNode *updatePaintNode(QSGNode *) = 0;
- virtual void notifyResize() = 0;
virtual void notifyShown() = 0;
virtual void notifyHidden() = 0;
- virtual void windowBoundsChanged() = 0;
- virtual void windowChanged() = 0;
+ virtual void visualPropertiesChanged() = 0;
virtual bool forwardEvent(QEvent *) = 0;
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) = 0;
virtual void closePopup() = 0;
@@ -92,8 +90,7 @@ class QWEBENGINECORE_PRIVATE_EXPORT RenderWidgetHostViewQtDelegate {
public:
virtual ~RenderWidgetHostViewQtDelegate() { }
virtual void initAsPopup(const QRect&) = 0;
- virtual QRectF screenRect() const = 0;
- virtual QRectF contentsRect() const = 0;
+ virtual QRectF viewGeometry() const = 0;
virtual void setKeyboardFocus() = 0;
virtual bool hasKeyboardFocus() = 0;
virtual void lockMouse() = 0;
diff --git a/src/core/resource_context_qt.h b/src/core/resource_context_qt.h
index 08359c79c..ccbe2c364 100644
--- a/src/core/resource_context_qt.h
+++ b/src/core/resource_context_qt.h
@@ -69,6 +69,7 @@ public:
extensions::ExtensionSystemQt* GetExtensionSystem();
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
private:
+ friend class ProfileIODataQt;
ProfileIODataQt* m_io_data;
DISALLOW_COPY_AND_ASSIGN(ResourceContextQt);
};
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index 96b4ecadc..7b1f1b4d6 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -172,6 +172,11 @@ inline gfx::SizeF toGfx(const QSizeF& size)
return gfx::SizeF(size.width(), size.height());
}
+inline gfx::Rect toGfx(const QRect &rect)
+{
+ return gfx::Rect(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
inline QSizeF toQt(const gfx::SizeF &size)
{
return QSizeF(size.width(), size.height());
diff --git a/src/core/user_notification_controller.cpp b/src/core/user_notification_controller.cpp
new file mode 100644
index 000000000..82cb57e51
--- /dev/null
+++ b/src/core/user_notification_controller.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "user_notification_controller.h"
+
+#include "type_conversion.h"
+
+#include "base/callback.h"
+#include "content/public/browser/notification_event_dispatcher.h"
+#include "third_party/blink/public/common/notifications/notification_resources.h"
+#include "third_party/blink/public/common/notifications/platform_notification_data.h"
+#include "ui/message_center/public/cpp/notification_delegate.h"
+
+#include <memory>
+
+namespace QtWebEngineCore {
+
+static Qt::LayoutDirection toDirection(blink::PlatformNotificationData::Direction direction)
+{
+ switch (direction) {
+ case blink::PlatformNotificationData::DIRECTION_LEFT_TO_RIGHT:
+ return Qt::LeftToRight;
+ case blink::PlatformNotificationData::DIRECTION_RIGHT_TO_LEFT:
+ return Qt::RightToLeft;
+ case blink::PlatformNotificationData::DIRECTION_AUTO:
+ default:
+ break;
+ }
+ return Qt::LayoutDirectionAuto;
+}
+
+class UserNotificationControllerPrivate {
+public:
+ UserNotificationControllerPrivate(const blink::PlatformNotificationData &params,
+ const blink::NotificationResources &resources,
+ const GURL &origin)
+ : m_params(params)
+ , m_origin(origin)
+ , m_delegate(nullptr)
+ , m_resources(resources)
+ , m_client(nullptr)
+ , m_iconGenerated(false)
+ , m_imageGenerated(false)
+ , m_badgeGenerated(false)
+ , m_shown(false)
+ { }
+
+ blink::PlatformNotificationData m_params;
+ GURL m_origin;
+ std::unique_ptr<UserNotificationController::Delegate> m_delegate;
+ blink::NotificationResources m_resources;
+ UserNotificationController::Client *m_client;
+ QIcon m_icon;
+ QImage m_image;
+ QImage m_badge;
+ bool m_iconGenerated;
+ bool m_imageGenerated;
+ bool m_badgeGenerated;
+ bool m_shown;
+};
+
+
+UserNotificationController::UserNotificationController(const blink::PlatformNotificationData &params,
+ const blink::NotificationResources &resources,
+ const GURL &origin,
+ Delegate *delegate)
+ : d(new UserNotificationControllerPrivate(params, resources, origin))
+{
+ d->m_delegate.reset(delegate);
+}
+
+UserNotificationController::~UserNotificationController()
+{
+ delete d;
+ d = nullptr;
+}
+
+void UserNotificationController::notificationDisplayed()
+{
+ if (!d->m_shown) {
+ d->m_shown = true;
+ if (d->m_delegate)
+ d->m_delegate->shown();
+ }
+}
+
+void UserNotificationController::notificationClosed()
+{
+ d->m_shown = false;
+ if (d->m_delegate)
+ d->m_delegate->closed(true);
+}
+
+void UserNotificationController::notificationClicked()
+{
+ if (d->m_delegate)
+ d->m_delegate->clicked();
+}
+
+void UserNotificationController::closeNotification()
+{
+ d->m_shown = false;
+ if (d->m_client)
+ d->m_client->notificationClosed(this);
+}
+
+void UserNotificationController::setClient(UserNotificationController::Client* client)
+{
+ d->m_client = client;
+}
+
+UserNotificationController::Client* UserNotificationController::client()
+{
+ return d->m_client;
+}
+
+QUrl UserNotificationController::origin() const
+{
+ return toQt(d->m_origin);
+}
+
+QIcon UserNotificationController::icon() const
+{
+ if (!d->m_iconGenerated) {
+ d->m_iconGenerated = true;
+ if (!d->m_resources.notification_icon.isNull()) {
+ QImage image = toQImage(d->m_resources.notification_icon);
+ if (!image.isNull())
+ d->m_icon = QIcon(QPixmap::fromImage(std::move(image), Qt::NoFormatConversion));
+ }
+ }
+ return d->m_icon;
+}
+
+QImage UserNotificationController::image() const
+{
+ if (d->m_imageGenerated)
+ return d->m_image;
+ d->m_image = toQImage(d->m_resources.image);
+ d->m_imageGenerated = true;
+ return d->m_image;
+}
+
+QImage UserNotificationController::badge() const
+{
+ if (d->m_badgeGenerated)
+ return d->m_badge;
+ d->m_badge = toQImage(d->m_resources.badge);
+ d->m_badgeGenerated = true;
+ return d->m_badge;
+}
+
+QString UserNotificationController::title() const
+{
+ return toQt(d->m_params.title);
+}
+
+QString UserNotificationController::body() const
+{
+ return toQt(d->m_params.body);
+}
+
+QString UserNotificationController::tag() const
+{
+ return toQt(d->m_params.tag);
+}
+
+QString UserNotificationController::language() const
+{
+ return toQt(d->m_params.lang);
+}
+
+Qt::LayoutDirection UserNotificationController::direction() const
+{
+ return toDirection(d->m_params.direction);
+}
+
+bool UserNotificationController::isShown() const
+{
+ return d->m_shown;
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/user_notification_controller.h b/src/core/user_notification_controller.h
new file mode 100644
index 000000000..840074843
--- /dev/null
+++ b/src/core/user_notification_controller.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DESKTOP_NOTIFICATION_CONTROLLER_H
+#define DESKTOP_NOTIFICATION_CONTROLLER_H
+
+#include "qtwebenginecoreglobal.h"
+
+#include <QtCore/QSharedPointer>
+#include <QtCore/QUrl>
+#include <QtGui/QIcon>
+
+class GURL;
+
+namespace blink {
+ struct NotificationResources;
+ struct PlatformNotificationData;
+}
+
+namespace QtWebEngineCore {
+
+class UserNotificationControllerPrivate;
+
+// Works as an accessor and owner of chromium objects related to showing desktop notifications.
+class QWEBENGINECORE_EXPORT UserNotificationController : public QEnableSharedFromThis<UserNotificationController> {
+public:
+ struct Delegate {
+ virtual ~Delegate() { }
+ virtual void shown() = 0;
+ virtual void clicked() = 0;
+ virtual void closed(bool byUser) = 0;
+ };
+
+ UserNotificationController(const blink::PlatformNotificationData &params,
+ const blink::NotificationResources &resources,
+ const GURL &origin,
+ Delegate *delegate);
+ ~UserNotificationController();
+
+ // The notification was shown.
+ void notificationDisplayed();
+
+ // The notification was closed.
+ void notificationClosed();
+
+ // The user clicked on the notification.
+ void notificationClicked();
+
+ // Chromium requests to close the notification.
+ void closeNotification();
+
+ QUrl origin() const;
+ QIcon icon() const;
+ QImage image() const;
+ QImage badge() const;
+ QString title() const;
+ QString body() const;
+ QString tag() const;
+ QString language() const;
+ Qt::LayoutDirection direction() const;
+
+ bool isShown() const;
+
+ class Client {
+ public:
+ virtual ~Client() { }
+ virtual void notificationClosed(const UserNotificationController *) = 0;
+ };
+ void setClient(Client *client);
+ Client* client();
+
+private:
+ UserNotificationControllerPrivate *d;
+};
+
+} // namespace QtWebEngineCore
+
+#endif // DESKTOP_NOTIFICATION_CONTROLLER_H
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 0c884d265..fe31a5b51 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -644,13 +644,12 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request)
"HTTP-POST data can only be sent over HTTP(S) protocol"));
return;
}
+ params.post_data = network::ResourceRequestBody::CreateFromBytes(
+ (const char*)request.postData().constData(),
+ request.postData().length());
break;
}
- params.post_data = network::ResourceRequestBody::CreateFromBytes(
- (const char*)request.postData().constData(),
- request.postData().length());
-
// convert the custom headers into the format that chromium expects
QVector<QByteArray> headers = request.headers();
for (QVector<QByteArray>::const_iterator it = headers.cbegin(); it != headers.cend(); ++it) {
@@ -1271,6 +1270,12 @@ void WebContentsAdapter::runGeolocationRequestCallback(const QUrl &securityOrigi
m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::GeolocationPermission, allowed);
}
+void WebContentsAdapter::runUserNotificationRequestCallback(const QUrl &securityOrigin, bool allowed)
+{
+ CHECK_INITIALIZED();
+ m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::NotificationPermission, allowed);
+}
+
void WebContentsAdapter::grantMouseLockPermission(bool granted)
{
CHECK_INITIALIZED();
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index b4a01fb17..c6e4f2256 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -183,6 +183,7 @@ public:
void grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags);
void runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed);
void grantMouseLockPermission(bool granted);
+ void runUserNotificationRequestCallback(const QUrl &securityOrigin, bool allowed);
void setBackgroundColor(const QColor &color);
QAccessibleInterface *browserAccessible();
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index f4937f0d4..d155ed391 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -459,6 +459,7 @@ public:
virtual void runMouseLockPermissionRequest(const QUrl &securityOrigin) = 0;
virtual void runQuotaRequest(QWebEngineQuotaRequest) = 0;
virtual void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) = 0;
+ virtual void runUserNotificationPermissionRequest(const QUrl &securityOrigin) = 0;
virtual WebEngineSettings *webEngineSettings() const = 0;
RenderProcessTerminationStatus renderProcessExitStatus(int);
virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) = 0;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 963b89a3f..4fcf2944d 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -585,6 +585,11 @@ void WebContentsDelegateQt::requestGeolocationPermission(const QUrl &requestingO
m_viewClient->runGeolocationPermissionRequest(requestingOrigin);
}
+void WebContentsDelegateQt::requestUserNotificationPermission(const QUrl &requestingOrigin)
+{
+ m_viewClient->runUserNotificationPermissionRequest(requestingOrigin);
+}
+
extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition);
void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture)
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index 40f585767..77f6cc389 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -148,6 +148,7 @@ public:
void allowCertificateError(const QSharedPointer<CertificateErrorController> &);
void selectClientCert(const QSharedPointer<ClientCertSelectController> &);
void requestGeolocationPermission(const QUrl &requestingOrigin);
+ void requestUserNotificationPermission(const QUrl &requestingOrigin);
void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture);
FaviconManager *faviconManager();
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index 9bf767437..67639dc4f 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -361,48 +361,39 @@ WebEngineContext::WebEngineContext()
base::TaskScheduler::Create("Browser");
m_contentRunner.reset(content::ContentMainRunner::Create());
m_browserRunner.reset(content::BrowserMainRunner::Create());
+
#ifdef Q_OS_LINUX
// Call qputenv before BrowserMainRunnerImpl::Initialize is called.
// http://crbug.com/245466
qputenv("force_s3tc_enable", "true");
#endif
- QWebEngineUrlScheme qrcScheme(QByteArrayLiteral("qrc"));
- qrcScheme.setFlags(QWebEngineUrlScheme::SecureScheme
- | QWebEngineUrlScheme::LocalAccessAllowed
- | QWebEngineUrlScheme::ViewSourceAllowed);
- QWebEngineUrlScheme::registerScheme(qrcScheme);
+ if (QWebEngineUrlScheme::schemeByName(QByteArrayLiteral("qrc")) == QWebEngineUrlScheme()) {
+ // User might have registered "qrc" already with different options.
+ QWebEngineUrlScheme qrcScheme(QByteArrayLiteral("qrc"));
+ qrcScheme.setFlags(QWebEngineUrlScheme::SecureScheme
+ | QWebEngineUrlScheme::LocalAccessAllowed
+ | QWebEngineUrlScheme::ViewSourceAllowed);
+ QWebEngineUrlScheme::registerScheme(qrcScheme);
+ }
+
+ QWebEngineUrlScheme::lockSchemes();
// Allow us to inject javascript like any webview toolkit.
content::RenderFrameHost::AllowInjectingJavaScriptForAndroidWebView();
- base::CommandLine::CreateEmpty();
- base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess();
QStringList appArgs = QCoreApplication::arguments();
- if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) {
- appArgs = appArgs.mid(0, 1); // Take application name and drop the rest
- appArgs.append(QString::fromLocal8Bit(qgetenv(kChromiumFlagsEnv)).split(' '));
- }
- bool enableWebGLSoftwareRendering =
- appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering"));
+ bool enableWebGLSoftwareRendering = appArgs.contains(QStringLiteral("--enable-webgl-software-rendering"));
bool useEmbeddedSwitches = false;
#if defined(QTWEBENGINE_EMBEDDED_SWITCHES)
- useEmbeddedSwitches = !appArgs.removeAll(QStringLiteral("--disable-embedded-switches"));
+ useEmbeddedSwitches = !appArgs.contains(QStringLiteral("--disable-embedded-switches"));
#else
- useEmbeddedSwitches = appArgs.removeAll(QStringLiteral("--enable-embedded-switches"));
+ useEmbeddedSwitches = appArgs.contains(QStringLiteral("--enable-embedded-switches"));
#endif
- base::CommandLine::StringVector argv;
- argv.resize(appArgs.size());
-#if defined(Q_OS_WIN)
- for (int i = 0; i < appArgs.size(); ++i)
- argv[i] = toString16(appArgs[i]);
-#else
- for (int i = 0; i < appArgs.size(); ++i)
- argv[i] = appArgs[i].toStdString();
-#endif
- parsedCommandLine->InitFromArgv(argv);
+
+ base::CommandLine* parsedCommandLine = commandLine();
parsedCommandLine->AppendSwitchPath(switches::kBrowserSubprocessPath, WebEngineLibraryInfo::getPath(content::CHILD_PROCESS_EXE));
@@ -665,4 +656,34 @@ gpu::SyncPointManager *WebEngineContext::syncPointManager()
return s_syncPointManager.load();
}
+base::CommandLine* WebEngineContext::commandLine() {
+ if (base::CommandLine::CreateEmpty()) {
+ base::CommandLine* parsedCommandLine = base::CommandLine::ForCurrentProcess();
+ QStringList appArgs = QCoreApplication::arguments();
+ if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) {
+ appArgs = appArgs.mid(0, 1); // Take application name and drop the rest
+ appArgs.append(QString::fromLocal8Bit(qgetenv(kChromiumFlagsEnv)).split(' '));
+ }
+#ifdef Q_OS_WIN
+ appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering"));
+#endif
+ appArgs.removeAll(QStringLiteral("--disable-embedded-switches"));
+ appArgs.removeAll(QStringLiteral("--enable-embedded-switches"));
+
+ base::CommandLine::StringVector argv;
+ argv.resize(appArgs.size());
+#if defined(Q_OS_WIN)
+ for (int i = 0; i < appArgs.size(); ++i)
+ argv[i] = toString16(appArgs[i]);
+#else
+ for (int i = 0; i < appArgs.size(); ++i)
+ argv[i] = appArgs[i].toStdString();
+#endif
+ parsedCommandLine->InitFromArgv(argv);
+ return parsedCommandLine;
+ } else {
+ return base::CommandLine::ForCurrentProcess();
+ }
+}
+
} // namespace
diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h
index ad02ddf4d..4dc5251cc 100644
--- a/src/core/web_engine_context.h
+++ b/src/core/web_engine_context.h
@@ -47,6 +47,7 @@
namespace base {
class RunLoop;
+class CommandLine;
}
namespace content {
@@ -95,6 +96,7 @@ public:
void addProfileAdapter(ProfileAdapter *profileAdapter);
void removeProfileAdapter(ProfileAdapter *profileAdapter);
void destroy();
+ static base::CommandLine* commandLine();
static gpu::SyncPointManager *syncPointManager();
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index 4448d44d1..cf9dae90a 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -46,6 +46,7 @@
#include "qquickwebenginesettings_p.h"
#include "qquickwebengineview_p_p.h"
#include "qwebenginecookiestore.h"
+#include "qwebenginenotification.h"
#include <QQmlEngine>
@@ -150,6 +151,13 @@ ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::MimeHtmlSaveFormat, QtWebEngineC
The \a download argument holds the state of the finished download instance.
*/
+/*!
+ \fn QQuickWebEngineProfile::userNotification(QWebEngineNotification *notification)
+
+ This signal is emitted whenever there is a newly created user notification.
+ The \a notification argument holds the notification instance to query data and interact with.
+*/
+
QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(ProfileAdapter *profileAdapter)
: m_settings(new QQuickWebEngineSettings())
, m_profileAdapter(profileAdapter)
@@ -285,6 +293,14 @@ void QQuickWebEngineProfilePrivate::useForGlobalCertificateVerificationChanged()
Q_EMIT q->useForGlobalCertificateVerificationChanged();
}
+void QQuickWebEngineProfilePrivate::showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &controller)
+{
+ Q_Q(QQuickWebEngineProfile);
+ auto notification = new QWebEngineNotification(controller);
+ QQmlEngine::setObjectOwnership(notification, QQmlEngine::JavaScriptOwnership);
+ Q_EMIT q->userNotification(notification);
+}
+
void QQuickWebEngineProfilePrivate::userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script)
{
Q_ASSERT(p && p->data);
@@ -365,6 +381,13 @@ void QQuickWebEngineProfilePrivate::userScripts_clear(QQmlListProperty<QQuickWeb
*/
/*!
+ \qmlsignal WebEngineProfile::userNotification(WebEngineNotification notification)
+
+ This signal is emitted whenever there is a newly created user notification.
+ The \a notification argument holds the notification instance to query data and interact with.
+*/
+
+/*!
Constructs a new profile with the parent \a parent.
*/
QQuickWebEngineProfile::QQuickWebEngineProfile(QObject *parent)
@@ -922,20 +945,45 @@ void QQuickWebEngineProfile::clearHttpCache()
d->profileAdapter()->clearHttpCache();
}
-
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Registers a request interceptor singleton \a interceptor to intercept URL requests.
The profile does not take ownership of the pointer.
+ \obsolete
+
+ Interceptors installed with this method will call
+ QWebEngineUrlRequestInterceptor::interceptRequest on the I/O thread. Therefore
+ the user has to provide thread-safe interaction with the other user classes.
+ Use setUrlRequestInterceptor instead.
+
\sa QWebEngineUrlRequestInterceptor
+
*/
void QQuickWebEngineProfile::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
{
Q_D(QQuickWebEngineProfile);
+ interceptor->setProperty("deprecated", true);
+ d->profileAdapter()->setRequestInterceptor(interceptor);
+ qWarning("Use of deprecated not tread-safe setter, use setUrlRequestInterceptor instead.");
+}
+#endif
+
+/*!
+ Registers a request interceptor singleton \a interceptor to intercept URL requests.
+
+ The profile does not take ownership of the pointer.
+
+ \sa QWebEngineUrlRequestInfo QWebEngineUrlRequestInterceptor
+*/
+void QQuickWebEngineProfile::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
+{
+ Q_D(QQuickWebEngineProfile);
d->profileAdapter()->setRequestInterceptor(interceptor);
}
+
/*!
Returns the custom URL scheme handler register for the URL scheme \a scheme.
*/
diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h
index 1e2e3e030..ce3285ec9 100644
--- a/src/webengine/api/qquickwebengineprofile.h
+++ b/src/webengine/api/qquickwebengineprofile.h
@@ -55,6 +55,7 @@ class QQuickWebEngineProfilePrivate;
class QQuickWebEngineScript;
class QQuickWebEngineSettings;
class QWebEngineCookieStore;
+class QWebEngineNotification;
class QWebEngineUrlRequestInterceptor;
class QWebEngineUrlSchemeHandler;
@@ -126,7 +127,10 @@ public:
QWebEngineCookieStore *cookieStore() const;
+#if QT_DEPRECATED_SINCE(5, 13)
void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
+#endif
+ void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
const QWebEngineUrlSchemeHandler *urlSchemeHandler(const QByteArray &) const;
void installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *);
@@ -169,6 +173,8 @@ Q_SIGNALS:
void downloadRequested(QQuickWebEngineDownloadItem *download);
void downloadFinished(QQuickWebEngineDownloadItem *download);
+ void userNotification(QWebEngineNotification *notification);
+
private:
Q_DECLARE_PRIVATE(QQuickWebEngineProfile)
QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *, QObject *parent = Q_NULLPTR);
diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h
index d59470f46..322ec0101 100644
--- a/src/webengine/api/qquickwebengineprofile_p.h
+++ b/src/webengine/api/qquickwebengineprofile_p.h
@@ -85,6 +85,8 @@ public:
void useForGlobalCertificateVerificationChanged() override;
+ void showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &controller) override;
+
// QQmlListPropertyHelpers
static void userScripts_append(QQmlListProperty<QQuickWebEngineScript> *p, QQuickWebEngineScript *script);
static int userScripts_count(QQmlListProperty<QQuickWebEngineScript> *p);
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index 5e6a45924..e7b2d8c9c 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -320,6 +320,12 @@ void QQuickWebEngineViewPrivate::runGeolocationPermissionRequest(const QUrl &url
Q_EMIT q->featurePermissionRequested(url, QQuickWebEngineView::Geolocation);
}
+void QQuickWebEngineViewPrivate::runUserNotificationPermissionRequest(const QUrl &url)
+{
+ Q_Q(QQuickWebEngineView);
+ Q_EMIT q->featurePermissionRequested(url, QQuickWebEngineView::Notifications);
+}
+
void QQuickWebEngineViewPrivate::showColorDialog(QSharedPointer<ColorChooserController> controller)
{
Q_Q(QQuickWebEngineView);
@@ -1550,6 +1556,9 @@ void QQuickWebEngineView::grantFeaturePermission(const QUrl &securityOrigin, QQu
WebContentsAdapterClient::MediaDesktopAudioCapture |
WebContentsAdapterClient::MediaDesktopVideoCapture));
break;
+ case Notifications:
+ d_ptr->adapter->runUserNotificationRequestCallback(securityOrigin, granted);
+ break;
default:
Q_UNREACHABLE();
}
diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h
index 3a40abf0a..c851dcb8d 100644
--- a/src/webengine/api/qquickwebengineview_p.h
+++ b/src/webengine/api/qquickwebengineview_p.h
@@ -209,7 +209,8 @@ public:
MediaAudioVideoCapture,
Geolocation,
DesktopVideoCapture,
- DesktopAudioVideoCapture
+ DesktopAudioVideoCapture,
+ Notifications,
};
Q_ENUM(Feature)
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 4e8657651..543d7b119 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -145,6 +145,7 @@ public:
void allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController) override;
void selectClientCert(const QSharedPointer<ClientCertSelectController> &selectController) override;
void runGeolocationPermissionRequest(QUrl const&) override;
+ void runUserNotificationPermissionRequest(QUrl const&) override;
void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) override;
void requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) override;
void updateScrollPosition(const QPointF &position) override;
diff --git a/src/webengine/doc/src/qtwebengine-features.qdoc b/src/webengine/doc/src/qtwebengine-features.qdoc
index 1dce17e08..64e9badb1 100644
--- a/src/webengine/doc/src/qtwebengine-features.qdoc
+++ b/src/webengine/doc/src/qtwebengine-features.qdoc
@@ -50,6 +50,7 @@
\li \l{Touch}
\li \l{View Source}
\li \l{WebRTC}
+ \li \l{Notifications}
\endlist
\section1 Audio and Video Codecs
@@ -511,4 +512,13 @@
This feature can be tested by setting up a webcam or microphone and then
opening \c https://test.webrtc.org/ in \l{WebEngine Widgets Simple Browser
Example}{Simple Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser}.
+
+ \section1 Notifications
+
+ Qt WebEngine supports JavaScript Web Notification API.
+ The application has to explicitly allow the feature by using
+ QWebEnginePage::Notifications or \l{WebEngineView::Feature}
+ {WebEngineView.Notifications}.
+
+ Support for this feature was added in Qt 5.13.0.
*/
diff --git a/src/webengine/doc/src/webengineview_lgpl.qdoc b/src/webengine/doc/src/webengineview_lgpl.qdoc
index d96aabc97..a6f2af39e 100644
--- a/src/webengine/doc/src/webengineview_lgpl.qdoc
+++ b/src/webengine/doc/src/webengineview_lgpl.qdoc
@@ -858,6 +858,8 @@
(Added in Qt 5.10)
\value DesktopAudioVideoCapture
Both audio and video output capture. (Added in Qt 5.10)
+ \value WebEnginView.Notifications
+ Web notifications for the end-user.
\sa featurePermissionRequested(), grantFeaturePermission()
*/
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index 0e63989ee..82a76760d 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -55,6 +55,7 @@
#include <QtWebEngine/private/qquickwebenginetouchhandleprovider_p_p.h>
#include <QtWebEngine/private/qquickwebengineview_p.h>
#include <QtWebEngine/private/qquickwebengineaction_p.h>
+#include <QtWebEngineCore/qwebenginenotification.h>
#include <QtWebEngineCore/qwebenginequotarequest.h>
#include <QtWebEngineCore/qwebengineregisterprotocolhandlerrequest.h>
@@ -161,7 +162,7 @@ public:
tr("Cannot create a separate instance of WebEngineClientCertificateSelection"));
qmlRegisterUncreatableType<QQuickWebEngineClientCertificateOption>(uri, 1, 9, "WebEngineClientCertificateOption",
tr("Cannot create a separate instance of WebEngineClientCertificateOption"));
-
+ qmlRegisterUncreatableType<QWebEngineNotification>(uri, 1, 9, "WebEngineNotification", msgUncreatableType("WebEngineNotification"));
}
private:
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
index 2f65db97a..e756ee157 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
+++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp
@@ -63,7 +63,7 @@ RenderWidgetHostViewQtDelegateQuick::RenderWidgetHostViewQtDelegateQuick(RenderW
setFocus(true);
setActiveFocusOnTab(true);
-#ifdef Q_OS_OSX
+#if defined(Q_OS_MACOS) && !defined(QT_NO_OPENGL)
// Check that the default QSurfaceFormat OpenGL profile is compatible with the global OpenGL
// shared context profile, otherwise this could lead to a nasty crash.
QOpenGLContext *globalSharedContext = QOpenGLContext::globalShareContext();
@@ -99,19 +99,9 @@ void RenderWidgetHostViewQtDelegateQuick::initAsPopup(const QRect &r)
setVisible(true);
}
-QRectF RenderWidgetHostViewQtDelegateQuick::screenRect() const
+QRectF RenderWidgetHostViewQtDelegateQuick::viewGeometry() const
{
- QPointF pos = mapToScene(QPointF(0,0));
- return QRectF(pos.x(), pos.y(), width(), height());
-}
-
-QRectF RenderWidgetHostViewQtDelegateQuick::contentsRect() const
-{
- QPointF scenePoint = mapToScene(QPointF(0, 0));
- QPointF screenPos;
- if (window())
- screenPos = window()->mapToGlobal(scenePoint.toPoint());
- return QRectF(screenPos.x(), screenPos.y(), width(), height());
+ return QRectF(mapToGlobal(QPointF(0, 0)), size());
}
void RenderWidgetHostViewQtDelegateQuick::setKeyboardFocus()
@@ -322,16 +312,7 @@ void RenderWidgetHostViewQtDelegateQuick::inputMethodEvent(QInputMethodEvent *ev
void RenderWidgetHostViewQtDelegateQuick::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
QQuickItem::geometryChanged(newGeometry, oldGeometry);
-
- if (window()) {
- const QPointF globalPos = QQuickItem::mapToGlobal(position());
- if (globalPos != m_lastGlobalPos) {
- m_lastGlobalPos = globalPos;
- m_client->windowBoundsChanged();
- }
- }
-
- m_client->notifyResize();
+ m_client->visualPropertiesChanged();
}
void RenderWidgetHostViewQtDelegateQuick::itemChange(ItemChange change, const ItemChangeData &value)
@@ -347,8 +328,7 @@ void RenderWidgetHostViewQtDelegateQuick::itemChange(ItemChange change, const It
if (!m_isPopup)
m_windowConnections.append(connect(value.window, SIGNAL(closing(QQuickCloseEvent *)), SLOT(onHide())));
}
-
- m_client->windowChanged();
+ m_client->visualPropertiesChanged();
} else if (change == QQuickItem::ItemVisibleHasChanged) {
if (!m_isPopup && !value.boolValue)
onHide();
@@ -362,9 +342,7 @@ QSGNode *RenderWidgetHostViewQtDelegateQuick::updatePaintNode(QSGNode *oldNode,
void RenderWidgetHostViewQtDelegateQuick::onWindowPosChanged()
{
- if (window())
- m_lastGlobalPos = QQuickItem::mapToGlobal(position());
- m_client->windowBoundsChanged();
+ m_client->visualPropertiesChanged();
}
void RenderWidgetHostViewQtDelegateQuick::onHide()
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.h b/src/webengine/render_widget_host_view_qt_delegate_quick.h
index d4d64804a..4edf37cff 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quick.h
+++ b/src/webengine/render_widget_host_view_qt_delegate_quick.h
@@ -59,8 +59,7 @@ public:
~RenderWidgetHostViewQtDelegateQuick();
void initAsPopup(const QRect&) override;
- QRectF screenRect() const override;
- QRectF contentsRect() const override;
+ QRectF viewGeometry() const override;
void setKeyboardFocus() override;
bool hasKeyboardFocus() override;
void lockMouse() override;
@@ -113,7 +112,6 @@ private:
RenderWidgetHostViewQtDelegateClient *m_client;
QList<QMetaObject::Connection> m_windowConnections;
bool m_isPopup;
- QPointF m_lastGlobalPos;
QQuickWebEngineView *m_view = nullptr;
};
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp
index d3c88148e..3c6c743e0 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp
+++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.cpp
@@ -62,14 +62,9 @@ void RenderWidgetHostViewQtDelegateQuickWindow::initAsPopup(const QRect &screenR
show();
}
-QRectF RenderWidgetHostViewQtDelegateQuickWindow::screenRect() const
+QRectF RenderWidgetHostViewQtDelegateQuickWindow::viewGeometry() const
{
- return QRectF(x(), y(), width(), height());
-}
-
-QRectF RenderWidgetHostViewQtDelegateQuickWindow::contentsRect() const
-{
- return geometry();
+ return m_realDelegate->viewGeometry();
}
void RenderWidgetHostViewQtDelegateQuickWindow::show()
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h
index 36e4ddd8a..039f6102a 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h
+++ b/src/webengine/render_widget_host_view_qt_delegate_quickwindow.h
@@ -56,8 +56,7 @@ public:
~RenderWidgetHostViewQtDelegateQuickWindow();
void initAsPopup(const QRect&) override;
- QRectF screenRect() const override;
- QRectF contentsRect() const override;
+ QRectF viewGeometry() const override;
void setKeyboardFocus() override {}
bool hasKeyboardFocus() override { return false; }
void lockMouse() override {}
diff --git a/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp b/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp
new file mode 100644
index 000000000..c15a80373
--- /dev/null
+++ b/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwebenginenotificationpresenter_p.h"
+
+#include <QSystemTrayIcon>
+
+QT_BEGIN_NAMESPACE
+
+DefaultNotificationPresenter::DefaultNotificationPresenter(QObject *parent) : QObject(parent)
+{
+#ifndef QT_NO_SYSTEMTRAYICON
+ m_systemTrayIcon = new QSystemTrayIcon(this);
+ connect(m_systemTrayIcon, &QSystemTrayIcon::messageClicked, this, &DefaultNotificationPresenter::messageClicked);
+#endif
+}
+
+DefaultNotificationPresenter::~DefaultNotificationPresenter()
+{
+}
+
+void DefaultNotificationPresenter::show(const QWebEngineNotification &notification)
+{
+ if (!m_activeNotification.isNull())
+ m_activeNotification.close();
+ m_activeNotification = notification;
+#ifndef QT_NO_SYSTEMTRAYICON
+ if (m_systemTrayIcon) {
+ m_systemTrayIcon->show();
+ QIcon icon = notification.icon();
+ if (!icon.isNull())
+ m_systemTrayIcon->showMessage(notification.title(), notification.message(), icon);
+ else
+ m_systemTrayIcon->showMessage(notification.title(), notification.message());
+ notification.show();
+ connect(&m_activeNotification, &QWebEngineNotification::closed, this, &DefaultNotificationPresenter::closeNotification);
+ }
+#endif
+}
+
+void DefaultNotificationPresenter::messageClicked()
+{
+ if (!m_activeNotification.isNull())
+ m_activeNotification.click();
+}
+
+void DefaultNotificationPresenter::closeNotification()
+{
+#ifndef QT_NO_SYSTEMTRAYICON
+ const QWebEngineNotification *canceled = static_cast<const QWebEngineNotification *>(QObject::sender());
+ if (m_systemTrayIcon && canceled->matches(m_activeNotification))
+ m_systemTrayIcon->hide();
+#endif
+}
+
+void defaultNotificationPresenter(const QWebEngineNotification &notification)
+{
+ static DefaultNotificationPresenter *presenter = nullptr;
+ if (!presenter)
+ presenter = new DefaultNotificationPresenter();
+ presenter->show(notification);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/webenginewidgets/api/qwebenginenotificationpresenter_p.h b/src/webenginewidgets/api/qwebenginenotificationpresenter_p.h
new file mode 100644
index 000000000..a66dbc1b2
--- /dev/null
+++ b/src/webenginewidgets/api/qwebenginenotificationpresenter_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBENGINENOTIFICATIONPRESENTER_P_H
+#define QWEBENGINENOTIFICATIONPRESENTER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtWebEngineCore/QWebEngineNotification>
+
+#include <QtCore/QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QSystemTrayIcon;
+
+class DefaultNotificationPresenter : public QObject {
+ Q_OBJECT
+public:
+ DefaultNotificationPresenter(QObject *parent = nullptr);
+ virtual ~DefaultNotificationPresenter();
+
+ void show(const QWebEngineNotification &notification);
+
+private Q_SLOTS:
+ void messageClicked();
+ void closeNotification();
+
+private:
+ QSystemTrayIcon *m_systemTrayIcon;
+ QWebEngineNotification m_activeNotification;
+};
+
+void defaultNotificationPresenter(const QWebEngineNotification &notification);
+
+QT_END_NAMESPACE
+
+#endif // QWEBENGINENOTIFICATIONPRESENTER_P_H
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 3bc1a0b80..a1ddf88d7 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -54,6 +54,7 @@
#include "qwebenginefullscreenrequest.h"
#include "qwebenginehistory.h"
#include "qwebenginehistory_p.h"
+#include "qwebenginenotification.h"
#include "qwebengineprofile.h"
#include "qwebengineprofile_p.h"
#include "qwebenginequotarequest.h"
@@ -62,6 +63,7 @@
#include "qwebenginesettings.h"
#include "qwebengineview.h"
#include "qwebengineview_p.h"
+#include "user_notification_controller.h"
#include "render_widget_host_view_qt_delegate_widget.h"
#include "web_contents_adapter.h"
#include "web_engine_settings.h"
@@ -538,6 +540,12 @@ void QWebEnginePagePrivate::runRegisterProtocolHandlerRequest(QWebEngineRegister
Q_EMIT q->registerProtocolHandlerRequested(request);
}
+void QWebEnginePagePrivate::runUserNotificationPermissionRequest(const QUrl &securityOrigin)
+{
+ Q_Q(QWebEnginePage);
+ Q_EMIT q->featurePermissionRequested(securityOrigin, QWebEnginePage::Notifications);
+}
+
QObject *QWebEnginePagePrivate::accessibilityParentObject()
{
return view;
@@ -1797,7 +1805,7 @@ void QWebEnginePagePrivate::printRequested()
\sa QWebEngineUrlRequestInfo, QWebEngineProfile::setRequestInterceptor()
*/
-void QWebEnginePage::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
+void QWebEnginePage::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
{
Q_D(QWebEnginePage);
bool hadInterceptorChanged = bool(d->requestInterceptor) != bool(interceptor);
@@ -1874,6 +1882,7 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine
d->adapter->grantMouseLockPermission(true);
break;
case Notifications:
+ d->adapter->runUserNotificationRequestCallback(securityOrigin, true);
break;
}
} else { // if (policy == PermissionDeniedByUser)
@@ -1892,6 +1901,7 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine
d->adapter->grantMouseLockPermission(false);
break;
case Notifications:
+ d->adapter->runUserNotificationRequestCallback(securityOrigin, false);
break;
}
}
@@ -2372,6 +2382,10 @@ void QWebEnginePage::printToPdf(const QString &filePath, const QPageLayout &page
The \a resultCallback must take a const reference to a QByteArray as parameter. If printing was successful, this byte array
will contain the PDF data, otherwise, the byte array will be empty.
+ \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done
+ during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid
+ value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it.
+
\since 5.7
*/
void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &resultCallback, const QPageLayout &pageLayout)
@@ -2404,6 +2418,11 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res
The \a resultCallback must take a boolean as parameter. If printing was successful, this
boolean will have the value \c true, otherwise, its value will be \c false.
+
+ \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done
+ during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid
+ value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it.
+
\since 5.8
*/
void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &resultCallback)
diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h
index 4fd195074..4956877a9 100644
--- a/src/webenginewidgets/api/qwebenginepage.h
+++ b/src/webenginewidgets/api/qwebenginepage.h
@@ -77,8 +77,6 @@ class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject {
Q_OBJECT
Q_PROPERTY(QString selectedText READ selectedText)
Q_PROPERTY(bool hasSelection READ hasSelection)
-
- // Ex-QWebFrame properties
Q_PROPERTY(QUrl requestedUrl READ requestedUrl)
Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor)
Q_PROPERTY(QString title READ title)
@@ -187,9 +185,7 @@ public:
Q_ENUM(NavigationType)
enum Feature {
-#ifndef Q_QDOC
Notifications = 0,
-#endif
Geolocation = 1,
MediaAudioCapture = 2,
MediaVideoCapture,
@@ -306,7 +302,7 @@ public:
void setDevToolsPage(QWebEnginePage *page);
QWebEnginePage *devToolsPage() const;
- void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
+ void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
const QWebEngineContextMenuData &contextMenuData() const;
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index bf2f43f80..d597383e2 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -132,6 +132,7 @@ public:
void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) override;
void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override;
void runGeolocationPermissionRequest(const QUrl &securityOrigin) override;
+ void runUserNotificationPermissionRequest(const QUrl &securityOrigin) override;
void runMouseLockPermissionRequest(const QUrl &securityOrigin) override;
void runQuotaRequest(QWebEngineQuotaRequest) override;
void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) override;
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index 7e80f9720..74dc14da0 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -43,6 +43,7 @@
#include "qwebenginecookiestore.h"
#include "qwebenginedownloaditem.h"
#include "qwebenginedownloaditem_p.h"
+#include "qwebenginenotificationpresenter_p.h"
#include "qwebenginepage.h"
#include "qwebenginepage_p.h"
#include "qwebenginesettings.h"
@@ -140,6 +141,12 @@ using QtWebEngineCore::ProfileAdapter;
Both session and persistent cookies are saved to and restored from disk.
*/
+void QWebEngineProfilePrivate::showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &notification)
+{
+ if (m_notificationPresenter)
+ m_notificationPresenter(QWebEngineNotification(notification));
+}
+
/*!
\fn QWebEngineProfile::downloadRequested(QWebEngineDownloadItem *download)
@@ -550,19 +557,43 @@ QWebEngineCookieStore* QWebEngineProfile::cookieStore()
return d->profileAdapter()->cookieStore();
}
-
+#if QT_DEPRECATED_SINCE(5, 13)
/*!
Registers a request interceptor singleton \a interceptor to intercept URL requests.
The profile does not take ownership of the pointer.
+ \obsolete
+
+ Interceptors installed with this method will call
+ QWebEngineUrlRequestInterceptor::interceptRequest on the I/O thread. Therefore
+ the user has to provide thread-safe interaction with the other user classes.
+ Use setUrlRequestInterceptor instead.
+
\since 5.6
\sa QWebEngineUrlRequestInfo
-*/
+*/
void QWebEngineProfile::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
{
Q_D(QWebEngineProfile);
+ interceptor->setProperty("deprecated", true);
+ d->profileAdapter()->setRequestInterceptor(interceptor);
+ qWarning("Use of deprecated not tread-safe setter, use setUrlRequestInterceptor instead.");
+}
+#endif
+/*!
+ Registers a request interceptor singleton \a interceptor to intercept URL requests.
+
+ The profile does not take ownership of the pointer.
+
+ \since 5.13
+ \sa QWebEngineUrlRequestInfo QWebEngineUrlRequestInterceptor
+*/
+
+void QWebEngineProfile::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
+{
+ Q_D(QWebEngineProfile);
d->profileAdapter()->setRequestInterceptor(interceptor);
}
@@ -610,6 +641,27 @@ QWebEngineScriptCollection *QWebEngineProfile::scripts() const
}
/*!
+ Sets the function \a notificationPresenter as responsible for presenting sent notifications.
+
+ \since 5.13
+ \sa QWebEngineNotification
+*/
+void QWebEngineProfile::setNotificationPresenter(const std::function<void(const QWebEngineNotification &)> &notificationPresenter)
+{
+ Q_D(QWebEngineProfile);
+ d->m_notificationPresenter = notificationPresenter;
+}
+
+/*!
+ \overload
+*/
+void QWebEngineProfile::setNotificationPresenter(std::function<void(const QWebEngineNotification &)> &&notificationPresenter)
+{
+ Q_D(QWebEngineProfile);
+ d->m_notificationPresenter = std::move(notificationPresenter);
+}
+
+/*!
Returns the default profile.
The default profile uses the storage name "Default".
@@ -621,6 +673,8 @@ QWebEngineProfile *QWebEngineProfile::defaultProfile()
static QWebEngineProfile* profile = new QWebEngineProfile(
new QWebEngineProfilePrivate(ProfileAdapter::createDefaultProfileAdapter()),
ProfileAdapter::globalQObjectRoot());
+ if (!profile->d_ptr->m_notificationPresenter)
+ profile->setNotificationPresenter(&defaultNotificationPresenter);
return profile;
}
diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h
index 9fc509851..5ad999c00 100644
--- a/src/webenginewidgets/api/qwebengineprofile.h
+++ b/src/webenginewidgets/api/qwebengineprofile.h
@@ -46,12 +46,15 @@
#include <QtCore/qscopedpointer.h>
#include <QtCore/qstring.h>
+#include <functional>
+
QT_BEGIN_NAMESPACE
class QObject;
class QUrl;
class QWebEngineCookieStore;
class QWebEngineDownloadItem;
+class QWebEngineNotification;
class QWebEnginePage;
class QWebEnginePagePrivate;
class QWebEngineProfilePrivate;
@@ -106,7 +109,10 @@ public:
void setHttpCacheMaximumSize(int maxSize);
QWebEngineCookieStore* cookieStore();
+#if QT_DEPRECATED_SINCE(5, 13)
void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
+#endif
+ void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
void clearAllVisitedLinks();
void clearVisitedLinks(const QList<QUrl> &urls);
@@ -134,6 +140,9 @@ public:
QString downloadPath() const;
void setDownloadPath(const QString &path);
+ void setNotificationPresenter(const std::function<void(const QWebEngineNotification &)> &notificationPresenter);
+ void setNotificationPresenter(std::function<void(const QWebEngineNotification &)> &&notificationPresenter);
+
static QWebEngineProfile *defaultProfile();
Q_SIGNALS:
diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h
index 9ff8df849..3dd024ffd 100644
--- a/src/webenginewidgets/api/qwebengineprofile_p.h
+++ b/src/webenginewidgets/api/qwebengineprofile_p.h
@@ -60,6 +60,8 @@
#include <QScopedPointer>
#include <QSharedPointer>
+#include <functional>
+
namespace QtWebEngineCore {
class ProfileAdapter;
}
@@ -68,6 +70,7 @@ QT_BEGIN_NAMESPACE
class QWebEngineBrowserContext;
class QWebEngineProfilePrivate;
+class QWebEngineNotification;
class QWebEngineSettings;
class QWebEngineProfilePrivate : public QtWebEngineCore::ProfileAdapterClient {
@@ -84,12 +87,15 @@ public:
void downloadRequested(DownloadItemInfo &info) override;
void downloadUpdated(const DownloadItemInfo &info) override;
+ void showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &) override;
+
private:
QWebEngineProfile *q_ptr;
QWebEngineSettings *m_settings;
QPointer<QtWebEngineCore::ProfileAdapter> m_profileAdapter;
QScopedPointer<QWebEngineScriptCollection> m_scriptCollection;
QMap<quint32, QPointer<QWebEngineDownloadItem> > m_ongoingDownloads;
+ std::function<void(const QWebEngineNotification &)> m_notificationPresenter;
};
QT_END_NAMESPACE
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index d012c678c..877bf7175 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -285,6 +285,8 @@
This enum describes the platform feature access categories that the user may be asked to grant
or deny access to:
+ \value Notifications
+ Web notifications for the end-user.
\value Geolocation
Location hardware or service.
\value MediaAudioCapture
@@ -485,6 +487,10 @@
The \a resultCallback must take a boolean parameter. It will be called with a value of \c true
if the \a subString was found; otherwise the callback value will be \c false.
+ \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done
+ during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid
+ value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it.
+
For example:
\snippet qtwebengine_qwebenginepage_snippet.cpp 0
*/
@@ -613,6 +619,10 @@
\note \a resultCallback can be any of a function pointer, a functor or a lambda, and it is expected to take a QString parameter.
+ \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done
+ during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid
+ value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it.
+
\sa setHtml(), toPlainText()
*/
@@ -624,6 +634,10 @@
\note \a resultCallback can be any of a function pointer, a functor or a lambda, and it is expected to take a QString parameter.
+ \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done
+ during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid
+ value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it.
+
\sa toHtml()
*/
@@ -743,6 +757,10 @@
\warning Do not execute lengthy routines in the callback function, because it might block the
rendering of the web engine page.
+ \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done
+ during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid
+ value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it.
+
See scripts() for an alternative API to inject scripts.
\sa QWebEngineScript::ScriptWorldId
diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
index 09346a446..501959ab9 100644
--- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
@@ -252,6 +252,10 @@
\a resultCallback must take a boolean parameter. It will be called with a value of \c true
if \a subString was found; otherwise the callback value will be \c false.
+ \warning We guarantee that the callback (\a resultCallback) is always called, but it might be done
+ during page destruction. When QWebEnginePage is deleted, the callback is triggered with an invalid
+ value and it is not safe to use the corresponding QWebEnginePage or QWebEngineView instance inside it.
+
\sa selectedText(), selectionChanged()
*/
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 5b464a461..951360c05 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -233,15 +233,9 @@ void RenderWidgetHostViewQtDelegateWidget::closeEvent(QCloseEvent *event)
m_client->closePopup();
}
-QRectF RenderWidgetHostViewQtDelegateWidget::screenRect() const
+QRectF RenderWidgetHostViewQtDelegateWidget::viewGeometry() const
{
- return QRectF(x(), y(), width(), height());
-}
-
-QRectF RenderWidgetHostViewQtDelegateWidget::contentsRect() const
-{
- QPointF pos = mapToGlobal(QPoint(0, 0));
- return QRectF(pos.x(), pos.y(), width(), height());
+ return QRectF(mapToGlobal(pos()), size());
}
void RenderWidgetHostViewQtDelegateWidget::setKeyboardFocus()
@@ -283,6 +277,7 @@ void RenderWidgetHostViewQtDelegateWidget::show()
void RenderWidgetHostViewQtDelegateWidget::hide()
{
m_rootItem->setVisible(false);
+ QQuickWidget::hide();
}
bool RenderWidgetHostViewQtDelegateWidget::isVisible() const
@@ -378,14 +373,7 @@ QVariant RenderWidgetHostViewQtDelegateWidget::inputMethodQuery(Qt::InputMethodQ
void RenderWidgetHostViewQtDelegateWidget::resizeEvent(QResizeEvent *resizeEvent)
{
QQuickWidget::resizeEvent(resizeEvent);
-
- const QPoint globalPos = mapToGlobal(pos());
- if (globalPos != m_lastGlobalPos) {
- m_lastGlobalPos = globalPos;
- m_client->windowBoundsChanged();
- }
-
- m_client->notifyResize();
+ m_client->visualPropertiesChanged();
}
void RenderWidgetHostViewQtDelegateWidget::showEvent(QShowEvent *event)
@@ -401,7 +389,7 @@ void RenderWidgetHostViewQtDelegateWidget::showEvent(QShowEvent *event)
m_windowConnections.append(connect(w, SIGNAL(xChanged(int)), SLOT(onWindowPosChanged())));
m_windowConnections.append(connect(w, SIGNAL(yChanged(int)), SLOT(onWindowPosChanged())));
}
- m_client->windowChanged();
+ m_client->visualPropertiesChanged();
m_client->notifyShown();
}
@@ -497,8 +485,7 @@ bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event)
void RenderWidgetHostViewQtDelegateWidget::onWindowPosChanged()
{
- m_lastGlobalPos = mapToGlobal(pos());
- m_client->windowBoundsChanged();
+ m_client->visualPropertiesChanged();
}
} // namespace QtWebEngineCore
diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
index c1cd90093..a736aa5cf 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
@@ -66,8 +66,7 @@ public:
~RenderWidgetHostViewQtDelegateWidget();
void initAsPopup(const QRect&) override;
- QRectF screenRect() const override;
- QRectF contentsRect() const override;
+ QRectF viewGeometry() const override;
void setKeyboardFocus() override;
bool hasKeyboardFocus() override;
void lockMouse() override;
@@ -111,7 +110,6 @@ private:
QScopedPointer<QQuickItem> m_rootItem;
bool m_isPopup;
QColor m_clearColor;
- QPoint m_lastGlobalPos;
QList<QMetaObject::Connection> m_windowConnections;
QWebEnginePage *m_page = nullptr;
QMetaObject::Connection m_parentDestroyedConnection;
diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro
index 4669c2bce..d4fb40dc7 100644
--- a/src/webenginewidgets/webenginewidgets.pro
+++ b/src/webenginewidgets/webenginewidgets.pro
@@ -19,6 +19,7 @@ SOURCES = \
api/qwebenginedownloaditem.cpp \
api/qwebenginefullscreenrequest.cpp \
api/qwebenginehistory.cpp \
+ api/qwebenginenotificationpresenter.cpp \
api/qwebenginepage.cpp \
api/qwebengineprofile.cpp \
api/qwebenginescript.cpp \
@@ -36,6 +37,7 @@ HEADERS = \
api/qwebenginedownloaditem_p.h \
api/qwebenginefullscreenrequest.h \
api/qwebenginehistory.h \
+ api/qwebenginenotificationpresenter_p.h \
api/qwebenginepage.h \
api/qwebenginepage_p.h \
api/qwebengineprofile.h \
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
index 7b7fec6f4..5629998fd 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -107,6 +107,7 @@ public:
void interceptRequest(QWebEngineUrlRequestInfo &info) override
{
+ QVERIFY(QThread::currentThread() == QCoreApplication::instance()->thread());
// Since 63 we also intercept some unrelated blob requests..
if (info.requestUrl().scheme() == QLatin1String("blob"))
return;
@@ -167,7 +168,7 @@ void tst_QWebEngineUrlRequestInterceptor::interceptRequest()
QWebEngineProfile profile;
profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
TestRequestInterceptor interceptor(/* intercept */ true);
- profile.setRequestInterceptor(&interceptor);
+ profile.setUrlRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
@@ -197,7 +198,7 @@ void tst_QWebEngineUrlRequestInterceptor::interceptRequest()
// Make sure that registering an observer does not modify the request.
TestRequestInterceptor observer(/* intercept */ false);
- profile.setRequestInterceptor(&observer);
+ profile.setUrlRequestInterceptor(&observer);
page.load(QUrl("qrc:///resources/__placeholder__"));
QTRY_COMPARE(loadSpy.count(), 1);
success = loadSpy.takeFirst().takeFirst();
@@ -230,7 +231,7 @@ void tst_QWebEngineUrlRequestInterceptor::ipv6HostEncoding()
{
QWebEngineProfile profile;
LocalhostContentProvider contentProvider;
- profile.setRequestInterceptor(&contentProvider);
+ profile.setUrlRequestInterceptor(&contentProvider);
QWebEnginePage page(&profile);
QSignalSpy spyLoadFinished(&page, SIGNAL(loadFinished(bool)));
@@ -264,11 +265,11 @@ void tst_QWebEngineUrlRequestInterceptor::requestedUrl()
profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
TestRequestInterceptor interceptor(/* intercept */ true);
if (!interceptInPage)
- profile.setRequestInterceptor(&interceptor);
+ profile.setUrlRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
if (interceptInPage)
- page.setRequestInterceptor(&interceptor);
+ page.setUrlRequestInterceptor(&interceptor);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.setUrl(QUrl("qrc:///resources/__placeholder__"));
@@ -303,11 +304,11 @@ void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl()
QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ true);
if (!interceptInPage)
- profile.setRequestInterceptor(&interceptor);
+ profile.setUrlRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
if (interceptInPage)
- page.setRequestInterceptor(&interceptor);
+ page.setUrlRequestInterceptor(&interceptor);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.setUrl(QUrl("qrc:///resources/__placeholder__"));
@@ -336,7 +337,7 @@ void tst_QWebEngineUrlRequestInterceptor::firstPartyUrl()
{
QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ false);
- profile.setRequestInterceptor(&interceptor);
+ profile.setUrlRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
@@ -370,7 +371,7 @@ void tst_QWebEngineUrlRequestInterceptor::firstPartyUrlNestedIframes()
QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ false);
- profile.setRequestInterceptor(&interceptor);
+ profile.setUrlRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
@@ -431,7 +432,7 @@ void tst_QWebEngineUrlRequestInterceptor::requestInterceptorByResourceType()
QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ false);
- profile.setRequestInterceptor(&interceptor);
+ profile.setUrlRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
@@ -449,7 +450,7 @@ void tst_QWebEngineUrlRequestInterceptor::firstPartyUrlHttp()
{
QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ false);
- profile.setRequestInterceptor(&interceptor);
+ profile.setUrlRequestInterceptor(&interceptor);
QWebEnginePage page(&profile);
QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index 4cbadfdaa..b50a7d782 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -35,6 +35,7 @@
#include <QtTest/QtTest>
#include <QtWebEngine/QQuickWebEngineProfile>
#include <QtWebEngine/QQuickWebEngineScript>
+#include <QtWebEngineCore/QWebEngineNotification>
#include <QtWebEngineCore/QWebEngineQuotaRequest>
#include <QtWebEngineCore/QWebEngineRegisterProtocolHandlerRequest>
#include <private/qquickwebengineview_p.h>
@@ -82,6 +83,7 @@ static const QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *
<< &QQuickWebEngineContextMenuRequest::staticMetaObject
<< &QWebEngineQuotaRequest::staticMetaObject
<< &QWebEngineRegisterProtocolHandlerRequest::staticMetaObject
+ << &QWebEngineNotification::staticMetaObject
;
static QList<const char *> knownEnumNames = QList<const char *>();
@@ -286,6 +288,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineProfile.clearHttpCache() --> void"
<< "QQuickWebEngineProfile.downloadFinished(QQuickWebEngineDownloadItem*) --> void"
<< "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadItem*) --> void"
+ << "QQuickWebEngineProfile.userNotification(QWebEngineNotification*) --> void"
<< "QQuickWebEngineProfile.httpAcceptLanguage --> QString"
<< "QQuickWebEngineProfile.httpAcceptLanguageChanged() --> void"
<< "QQuickWebEngineProfile.httpCacheMaximumSize --> int"
@@ -564,6 +567,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.NewViewInTab --> NewViewDestination"
<< "QQuickWebEngineView.NewViewInWindow --> NewViewDestination"
<< "QQuickWebEngineView.NoErrorDomain --> ErrorDomain"
+ << "QQuickWebEngineView.Notifications --> Feature"
<< "QQuickWebEngineView.NoWebAction --> WebAction"
<< "QQuickWebEngineView.NormalTerminationStatus --> RenderProcessTerminationStatus"
<< "QQuickWebEngineView.Note --> PrintedPageSizeId"
@@ -703,6 +707,20 @@ static const QStringList expectedAPI = QStringList()
<< "QWebEngineRegisterProtocolHandlerRequest.origin --> QUrl"
<< "QWebEngineRegisterProtocolHandlerRequest.reject() --> void"
<< "QWebEngineRegisterProtocolHandlerRequest.scheme --> QString"
+ << "QWebEngineNotification.origin --> QUrl"
+ << "QWebEngineNotification.icon --> QIcon"
+ << "QWebEngineNotification.title --> QString"
+ << "QWebEngineNotification.message --> QString"
+ << "QWebEngineNotification.tag --> QString"
+ << "QWebEngineNotification.language --> QString"
+ << "QWebEngineNotification.direction --> Direction"
+ << "QWebEngineNotification.LeftToRight --> Direction"
+ << "QWebEngineNotification.RightToLeft --> Direction"
+ << "QWebEngineNotification.DirectionAuto --> Direction"
+ << "QWebEngineNotification.show() --> void"
+ << "QWebEngineNotification.click() --> void"
+ << "QWebEngineNotification.close() --> void"
+ << "QWebEngineNotification.closed() --> void"
;
static bool isCheckedEnum(const QByteArray &typeName)
diff --git a/tests/auto/quick/qmltests/data/tst_notification.qml b/tests/auto/quick/qmltests/data/tst_notification.qml
new file mode 100644
index 000000000..609a04f61
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_notification.qml
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.2
+import QtTest 1.0
+import QtWebEngine 1.9
+
+TestWebEngineView {
+ id: view
+ width: 320
+ height: 320
+
+ property bool permissionRequested: false
+ property bool grantPermission: false
+
+ signal consoleMessage(string message)
+
+ SignalSpy {
+ id: spyRequest
+ target: view
+ signalName: 'featurePermissionRequested'
+ }
+
+ onFeaturePermissionRequested: {
+ if (feature === WebEngineView.Notifications) {
+ permissionRequested = true
+ view.grantFeaturePermission(securityOrigin, feature, grantPermission)
+ }
+ }
+
+ TestCase {
+ name: 'WebEngineNotification'
+ when: windowShown
+
+ function resolverUrl(html) {
+ return Qt.resolvedUrl('../../../shared/data/' + html)
+ }
+
+ function init() {
+ permissionRequested = false
+ spyRequest.clear()
+ }
+
+ function test_request_data() {
+ return [
+ { tag: 'grant', grant: true, permission: 'granted' },
+ { tag: 'deny', grant: false, permission: 'denied' },
+ ]
+ }
+
+ function test_request(data) {
+ grantPermission = data.grant
+
+ view.url = resolverUrl('notification.html')
+ verify(view.waitForLoadSucceeded())
+
+ view.runJavaScript('resetPermission()')
+ let result = {}
+
+ view.runJavaScript('getPermission()', function (permission) { result.permission = permission })
+ tryCompare(result, 'permission', 'default')
+
+ view.runJavaScript('requestPermission()')
+ spyRequest.wait()
+ verify(permissionRequested)
+ compare(spyRequest.count, 1)
+
+ view.runJavaScript('getPermission()', function (permission) { result.permission = permission })
+ tryCompare(result, 'permission', data.permission)
+ }
+
+ function test_notification() {
+ grantPermission = true
+
+ view.url = resolverUrl('notification.html')
+ view.waitForLoadSucceeded()
+
+ view.runJavaScript('requestPermission()')
+ spyRequest.wait()
+ verify(permissionRequested)
+
+ let title = 'Title', message = 'Message', notification = null
+ view.profile.userNotification.connect(function (n) { notification = n })
+
+ view.runJavaScript('sendNotification("' + title + '", "' + message + '")')
+ tryVerify(function () { return notification !== null })
+ compare(notification.title, title)
+ compare(notification.message, message)
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index ad479cd31..00e884e11 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -67,6 +67,7 @@ OTHER_FILES += \
$$PWD/data/tst_navigationHistory.qml \
$$PWD/data/tst_navigationRequested.qml \
$$PWD/data/tst_newViewRequest.qml \
+ $$PWD/data/tst_notification.qml \
$$PWD/data/tst_profile.qml \
$$PWD/data/tst_properties.qml \
$$PWD/data/tst_runJavaScript.qml \
diff --git a/tests/auto/quick/qquickwebengineview/BLACKLIST b/tests/auto/quick/qquickwebengineview/BLACKLIST
index 5bb38576a..166a6894e 100644
--- a/tests/auto/quick/qquickwebengineview/BLACKLIST
+++ b/tests/auto/quick/qquickwebengineview/BLACKLIST
@@ -15,7 +15,3 @@ opensuse-leap
[javascriptClipboard:canPaste]
opensuse-leap
-
-[changeLocale]
-*
-
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index d467cd8ae..9817e7d6c 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -1001,6 +1001,7 @@ void tst_QQuickWebEngineView::changeLocale()
viewDE->setUrl(url);
QVERIFY(waitForLoadFailed(viewDE.data()));
+ QTRY_VERIFY(!evaluateJavaScriptSync(viewDE.data(), "document.body").isNull());
QTRY_VERIFY(!evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").isNull());
errorLines = evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").toString().split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar Die Server-IP-Adresse von non.existent wurde nicht gefunden."));
@@ -1010,9 +1011,10 @@ void tst_QQuickWebEngineView::changeLocale()
viewEN->setUrl(url);
QVERIFY(waitForLoadFailed(viewEN.data()));
+ QTRY_VERIFY(!evaluateJavaScriptSync(viewEN.data(), "document.body").isNull());
QTRY_VERIFY(!evaluateJavaScriptSync(viewEN.data(), "document.body.innerText").isNull());
errorLines = evaluateJavaScriptSync(viewEN.data(), "document.body.innerText").toString().split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
- QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("This site can\xE2\x80\x99t be reached"));
+ QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("This site can\xE2\x80\x99t be reached non.existent\xE2\x80\x99s server IP address could not be found."));
// Reset error page
viewDE->setUrl(QUrl("about:blank"));
@@ -1022,9 +1024,10 @@ void tst_QQuickWebEngineView::changeLocale()
viewDE->setUrl(url);
QVERIFY(waitForLoadFailed(viewDE.data()));
+ QTRY_VERIFY(!evaluateJavaScriptSync(viewDE.data(), "document.body").isNull());
QTRY_VERIFY(!evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").isNull());
errorLines = evaluateJavaScriptSync(viewDE.data(), "document.body.innerText").toString().split(QRegularExpression("[\r\n]"), QString::SkipEmptyParts);
- QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar"));
+ QCOMPARE(errorLines.first().toUtf8(), QByteArrayLiteral("Die Website ist nicht erreichbar Die Server-IP-Adresse von non.existent wurde nicht gefunden."));
}
void tst_QQuickWebEngineView::userScripts()
@@ -1110,6 +1113,39 @@ void tst_QQuickWebEngineView::javascriptClipboard()
QCOMPARE(evaluateJavaScriptSync(view, "document.execCommand('paste')").toBool(), pasteResult);
QCOMPARE(evaluateJavaScriptSync(view, "document.getElementById('myInput').value").toString(),
(pasteResult ? QString("AnotherText") : QString("OriginalText")));
+
+ // Test settings on clipboard permissions
+ evaluateJavaScriptSync(view,
+ QStringLiteral(
+ "var accessGranted = false;"
+ "var accessDenied = false;"
+ "var accessPrompt = false;"
+ "navigator.permissions.query({name:'clipboard-write'})"
+ ".then(result => {"
+ "if (result.state == 'granted') accessGranted = true;"
+ "if (result.state == 'denied') accessDenied = true;"
+ "if (result.state == 'prompt') accessPrompt = true;"
+ "})"));
+
+ QTRY_COMPARE(evaluateJavaScriptSync(view, "accessGranted").toBool(), copyResult);
+ QTRY_COMPARE(evaluateJavaScriptSync(view, "accessDenied").toBool(), !javascriptCanAccessClipboard);
+ QTRY_COMPARE(evaluateJavaScriptSync(view, "accessPrompt").toBool(), false);
+
+ evaluateJavaScriptSync(view,
+ QStringLiteral(
+ "accessGranted = false;"
+ "accessDenied = false;"
+ "accessPrompt = false;"
+ "navigator.permissions.query({name:'clipboard-read'})"
+ ".then(result => {"
+ "if (result.state == 'granted') accessGranted = true;"
+ "if (result.state == 'denied') accessDenied = true;"
+ "if (result.state == 'prompt') accessPrompt = true;"
+ "})"));
+
+ QTRY_COMPARE(evaluateJavaScriptSync(view, "accessGranted").toBool(), pasteResult);
+ QTRY_COMPARE(evaluateJavaScriptSync(view, "accessDenied").toBool(), !javascriptCanAccessClipboard || !javascriptCanPaste);
+ QTRY_COMPARE(evaluateJavaScriptSync(view, "accessPrompt").toBool(), false);
}
QTEST_MAIN(tst_QQuickWebEngineView)
diff --git a/tests/auto/shared/data/notification.html b/tests/auto/shared/data/notification.html
new file mode 100644
index 000000000..cadcbd942
--- /dev/null
+++ b/tests/auto/shared/data/notification.html
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+<head>
+<title>Desktop Notifications Demo</title>
+<script>
+ function resetPermission() { document.Notification = 'default' }
+
+ function getPermission() { return document.Notification }
+
+ function sendNotification(title, body) {
+ let notification = new Notification(title, { body: body })
+ notification.onclick = function() { console.info('onclick') }
+ notification.onclose = function() { console.info('onclose') }
+ notification.onerror = function(error) { console.info('onerror: ' + error) }
+ notification.onshow = function() { console.info('onshow') }
+ }
+
+ function makeNotification() {
+ let title = document.getElementById("title").value
+ let body = document.getElementById("body").value
+ console.log('making notification:', title)
+ sendNotification(title, body)
+ }
+
+ function requestPermission(callback) {
+ Notification.requestPermission().then(function (permission) {
+ document.Notification = permission
+ if (callback)
+ callback(permission)
+ })
+ }
+
+ function displayNotification() {
+ console.info('notifications are ' + document.Notification)
+
+ let state = document.getElementById('state')
+
+ if (document.Notification === 'denied') {
+ state.innerHTML = 'Notifications disabled'
+ } else if (document.Notification === 'granted') {
+ makeNotification()
+ state.innerHTML = 'notification created'
+ } else {
+ state.innerHTML = 'requesting permission...'
+ requestPermission(function (permission) {
+ console.info('notifications request: ' + permission)
+ if (permission === 'granted') {
+ makeNotification()
+ state.innerHTML = 'permission granted, notification created'
+ } else if (permission === 'denied')
+ state.innerHTML = 'Notifications are disabled'
+ })
+ }
+ }
+
+ document.addEventListener("DOMContentLoaded", function() {
+ document.Notification = Notification.permission
+ })
+</script>
+</head>
+<body>
+ <form name="NotificationForm" id="notificationForm">
+ Title: <input type="text" id="title" placeholder="Notification title" value='sample title'><br>
+ Body: <input type="text" id="body" placeholder="Notification body" value='default body'><br>
+ <input type="button" value="Display Notification" onclick="displayNotification()"><br>
+ <input type="button" value="Reset Permission" onclick="resetPermission()">
+ </form>
+ <div id='state'></div>
+</body>
+</html>
diff --git a/tests/auto/widgets/origins/tst_origins.cpp b/tests/auto/widgets/origins/tst_origins.cpp
index 61c7232b0..61d16bc8a 100644
--- a/tests/auto/widgets/origins/tst_origins.cpp
+++ b/tests/auto/widgets/origins/tst_origins.cpp
@@ -637,10 +637,7 @@ void tst_Origins::sharedWorker()
QTRY_VERIFY(eval(QSL("done")).toBool());
QCOMPARE(eval(QSL("result")), QVariant(42));
- // Even unregistered schemes can create SharedWorkers.
- QVERIFY(load(QSL("tst:/resources/sharedWorker.html")));
- QTRY_VERIFY(eval(QSL("done")).toBool());
- QCOMPARE(eval(QSL("result")), QVariant(42));
+ // Unregistered schemes should not create SharedWorkers.
QVERIFY(load(QSL("PathSyntax:/resources/sharedWorker.html")));
QTRY_VERIFY(eval(QSL("done")).toBool());
diff --git a/tests/auto/widgets/proxypac/proxypac.pro b/tests/auto/widgets/proxypac/proxypac.pro
index 00ae90977..1c2958d3a 100644
--- a/tests/auto/widgets/proxypac/proxypac.pro
+++ b/tests/auto/widgets/proxypac/proxypac.pro
@@ -3,26 +3,8 @@ QT += webengine
HEADERS += proxyserver.h
SOURCES += proxyserver.cpp
-# QTBUG-71229
-xgd_desktop.name=XDG_CURRENT_DESKTOP
-xgd_desktop.value=KDE
-QT_TOOL_ENV += xgd_desktop
+proxy_pac.name = QTWEBENGINE_CHROMIUM_FLAGS
+proxy_pac.value = --proxy-pac-url="file://$$PWD/proxy.pac"
-kde_home.name=KDEHOME
-kde_home.value=$$OUT_PWD
-QT_TOOL_ENV += kde_home
-
-PROXY_CONFIG= \
- "[Proxy Settings]" \
- "Proxy Config Script=$$PWD/proxy.pac" \
- "ProxyType=2"
-
-mkpath($$OUT_PWD/share/config)
-KDE_FILE = $$OUT_PWD/share/config/kioslaverc
-
-!build_pass {
- write_file($$KDE_FILE, PROXY_CONFIG)
-}
-
-QMAKE_DISTCLEAN += $$KDE_FILE
+QT_TOOL_ENV += proxy_pac
diff --git a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
index b50036aa8..32823d30d 100644
--- a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
+++ b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
@@ -620,7 +620,6 @@ void tst_QWebEngineDownloadItem::downloadPage_data()
void tst_QWebEngineDownloadItem::downloadPage()
{
- QSKIP("Unstable since Chromium 71");
QFETCH(QWebEngineDownloadItem::SavePageFormat, savePageFormat);
// Set up HTTP server
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 0b519fe8a..0504d39fa 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -49,6 +49,7 @@
#include <qwebenginedownloaditem.h>
#include <qwebenginefullscreenrequest.h>
#include <qwebenginehistory.h>
+#include <qwebenginenotification.h>
#include <qwebenginepage.h>
#include <qwebengineprofile.h>
#include <qwebenginequotarequest.h>
@@ -195,6 +196,10 @@ private Q_SLOTS:
void triggerActionWithoutMenu();
void dynamicFrame();
+ void notificationRequest_data();
+ void notificationRequest();
+ void sendNotification();
+
private:
static QPoint elementCenter(QWebEnginePage *page, const QString &id);
@@ -3202,6 +3207,96 @@ void tst_QWebEnginePage::dynamicFrame()
QCOMPARE(toPlainTextSync(&page).trimmed(), QStringLiteral("foo"));
}
+struct NotificationPage : ConsolePage {
+ Q_OBJECT
+ const QWebEnginePage::PermissionPolicy policy;
+
+public:
+ NotificationPage(QWebEnginePage::PermissionPolicy ppolicy) : policy(ppolicy) {
+ connect(this, &QWebEnginePage::loadFinished, [load = spyLoad.ref()] (bool result) mutable { load(result); });
+
+ connect(this, &QWebEnginePage::featurePermissionRequested,
+ [this] (const QUrl &origin, QWebEnginePage::Feature feature) {
+ if (feature != QWebEnginePage::Notifications)
+ return;
+ if (spyRequest.wasCalled())
+ QFAIL("request executed twise!");
+ setFeaturePermission(origin, feature, policy);
+ spyRequest.ref()(origin);
+ });
+
+ load(QStringLiteral("qrc:///shared/notification.html"));
+ }
+
+ CallbackSpy<bool> spyLoad;
+ CallbackSpy<QUrl> spyRequest;
+
+ QString getPermission() { return evaluateJavaScriptSync(this, "getPermission()").toString(); }
+ void requestPermission() { runJavaScript("requestPermission()"); }
+ void resetPermission() { runJavaScript("resetPermission()"); }
+ void sendNotification(const QString &title, const QString &body) {
+ runJavaScript("sendNotification('" + title + "', '" + body + "')");
+ }
+};
+
+void tst_QWebEnginePage::notificationRequest_data()
+{
+ QTest::addColumn<QWebEnginePage::PermissionPolicy>("policy");
+ QTest::addColumn<QString>("permission");
+ QTest::newRow("deny") << QWebEnginePage::PermissionDeniedByUser << "denied";
+ QTest::newRow("grant") << QWebEnginePage::PermissionGrantedByUser << "granted";
+}
+
+void tst_QWebEnginePage::notificationRequest()
+{
+ QFETCH(QWebEnginePage::PermissionPolicy, policy);
+ QFETCH(QString, permission);
+
+ NotificationPage page(policy);
+ QVERIFY(page.spyLoad.waitForResult());
+
+ page.resetPermission();
+ QCOMPARE(page.getPermission(), "default");
+
+ page.requestPermission();
+ page.spyRequest.waitForResult();
+ QVERIFY(page.spyRequest.wasCalled());
+
+ QCOMPARE(page.getPermission(), permission);
+}
+
+void tst_QWebEnginePage::sendNotification()
+{
+ NotificationPage page(QWebEnginePage::PermissionGrantedByUser);
+ QVERIFY(page.spyLoad.waitForResult());
+
+ page.resetPermission();
+ page.requestPermission();
+ auto origin = page.spyRequest.waitForResult();
+ QVERIFY(page.spyRequest.wasCalled());
+ QCOMPARE(page.getPermission(), "granted");
+
+ CallbackSpy<QWebEngineNotification> presenter;
+ page.profile()->setNotificationPresenter([callback = presenter.ref()] (const QWebEngineNotification &notification) mutable { callback(notification); });
+
+ QString title("Title"), message("Message");
+ page.sendNotification(title, message);
+
+ auto notification = presenter.waitForResult();
+ QVERIFY(presenter.wasCalled());
+ QVERIFY(!notification.isNull());
+ QCOMPARE(notification.title(), title);
+ QCOMPARE(notification.message(), message);
+ QCOMPARE(notification.origin(), origin);
+
+ notification.show();
+ QTRY_VERIFY2(page.messages.contains("onshow"), page.messages.join("\n").toLatin1().constData());
+ notification.click();
+ QTRY_VERIFY2(page.messages.contains("onclick"), page.messages.join("\n").toLatin1().constData());
+ notification.close();
+ QTRY_VERIFY2(page.messages.contains("onclose"), page.messages.join("\n").toLatin1().constData());
+}
+
static QByteArrayList params = {QByteArrayLiteral("--use-fake-device-for-media-stream")};
W_QTEST_MAIN(tst_QWebEnginePage, params)
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
index 3bb88cbe1..757e151c1 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
@@ -23,4 +23,7 @@
<file>resources/bar.txt</file>
<file>resources/path with spaces.txt</file>
</qresource>
+<qresource prefix='/shared'>
+ <file alias='notification.html'>../../shared/data/notification.html</file>
+</qresource>
</RCC>
diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
index bf5d320b7..b0db4e974 100644
--- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
+++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
@@ -31,6 +31,7 @@
#include <QtTest/QtTest>
#include <QtWebEngineCore/qwebengineurlrequestinterceptor.h>
#include <QtWebEngineCore/qwebengineurlrequestjob.h>
+#include <QtWebEngineCore/qwebenginecookiestore.h>
#include <QtWebEngineCore/qwebengineurlschemehandler.h>
#include <QtWebEngineWidgets/qwebengineprofile.h>
#include <QtWebEngineWidgets/qwebenginepage.h>
@@ -59,6 +60,7 @@ private Q_SLOTS:
void downloadItem();
void changePersistentPath();
void initiator();
+ void qtbug_72299(); // this should be the last test
};
void tst_QWebEngineProfile::init()
@@ -629,5 +631,19 @@ void tst_QWebEngineProfile::initiator()
QCOMPARE(handler.initiator, QUrl());
}
+void tst_QWebEngineProfile::qtbug_72299()
+{
+ QWebEngineView view;
+ view.setUrl(QUrl("https://www.qt.io"));
+ view.show();
+ QSignalSpy loadSpy(view.page(), SIGNAL(loadFinished(bool)));
+ view.page()->profile()->clearHttpCache();
+ view.page()->profile()->setHttpCacheType(QWebEngineProfile::NoCache);
+ view.page()->profile()->cookieStore()->deleteAllCookies();
+ view.page()->profile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
+ QTRY_COMPARE_WITH_TIMEOUT(loadSpy.count(), 1, 20000);
+}
+
+
QTEST_MAIN(tst_QWebEngineProfile)
#include "tst_qwebengineprofile.moc"
diff --git a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST
index e8758abcc..7c86a72d6 100644
--- a/tests/auto/widgets/qwebengineview/BLACKLIST
+++ b/tests/auto/widgets/qwebengineview/BLACKLIST
@@ -6,6 +6,3 @@ osx
[textSelectionOutOfInputField]
*
-
-[changeLocale]
-*
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index f2810101b..17177c7fb 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -46,6 +46,7 @@
#include <QTcpSocket>
#include <QStyle>
#include <QtWidgets/qaction.h>
+#include <QWebEngineProfile>
#include <QtCore/qregularexpression.h>
#define VERIFY_INPUTMETHOD_HINTS(actual, expect) \
@@ -194,6 +195,7 @@ private Q_SLOTS:
void jsKeyboardEvent();
void deletePage();
void closeOpenerTab();
+ void switchPage();
};
// This will be called before the first test function is executed.
@@ -3174,5 +3176,26 @@ void tst_QWebEngineView::closeOpenerTab()
QVERIFY(newView->focusProxy()->isVisible());
}
+void tst_QWebEngineView::switchPage()
+{
+ QWebEngineProfile profile;
+ QWebEnginePage page1(&profile);
+ QWebEnginePage page2(&profile);
+ QSignalSpy loadFinishedSpy1(&page1, SIGNAL(loadFinished(bool)));
+ QSignalSpy loadFinishedSpy2(&page2, SIGNAL(loadFinished(bool)));
+ page1.setHtml("<html><body bgcolor=\"#000000\"></body></html>");
+ page2.setHtml("<html><body bgcolor=\"#ffffff\"></body></html>");
+ QTRY_VERIFY(loadFinishedSpy1.count() && loadFinishedSpy2.count());
+ QWebEngineView webView;
+ webView.resize(300,300);
+ webView.show();
+ webView.setPage(&page1);
+ QTRY_COMPARE(webView.grab().toImage().pixelColor(QPoint(150,150)), Qt::black);
+ webView.setPage(&page2);
+ QTRY_COMPARE(webView.grab().toImage().pixelColor(QPoint(150,150)), Qt::white);
+ webView.setPage(&page1);
+ QTRY_COMPARE(webView.grab().toImage().pixelColor(QPoint(150,150)), Qt::black);
+}
+
QTEST_MAIN(tst_QWebEngineView)
#include "tst_qwebengineview.moc"
diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro
index eec8bb389..0addb9671 100644
--- a/tests/auto/widgets/widgets.pro
+++ b/tests/auto/widgets/widgets.pro
@@ -9,6 +9,7 @@ SUBDIRS += \
faviconmanager \
loadsignals \
origins \
+ proxypac \
schemes \
shutdown \
qwebenginedownloaditem \
@@ -27,9 +28,6 @@ qtConfig(webengine-printing-and-pdf) {
SUBDIRS += printing
}
-# QTBUG-71229
-linux:!boot2qt: SUBDIRS += proxypac
-
qtConfig(webengine-spellchecker):!cross_compile {
!qtConfig(webengine-native-spellchecker) {
SUBDIRS += spellchecking
@@ -43,4 +41,4 @@ boot2qt: SUBDIRS -= accessibility defaultsurfaceformat devtools \
faviconmanager qwebenginepage qwebenginehistory \
qwebengineprofile qwebenginescript \
qwebengineview qwebenginedownloaditem qwebenginesettings \
- schemes origins loadsignals
+ schemes origins loadsignals proxypac
diff --git a/tests/quicktestbrowser/ApplicationRoot.qml b/tests/quicktestbrowser/ApplicationRoot.qml
index 980016535..e2248e350 100644
--- a/tests/quicktestbrowser/ApplicationRoot.qml
+++ b/tests/quicktestbrowser/ApplicationRoot.qml
@@ -53,6 +53,7 @@ QtObject {
var newWindow = browserWindowComponent.createObject(root)
newWindow.currentWebView.profile = profile
profile.downloadRequested.connect(newWindow.onDownloadRequested)
+ profile.userNotification.connect(newWindow.onUserNotification)
return newWindow
}
function createDialog(profile) {
diff --git a/tests/quicktestbrowser/BrowserWindow.qml b/tests/quicktestbrowser/BrowserWindow.qml
index 22f98e1c5..381e9c142 100644
--- a/tests/quicktestbrowser/BrowserWindow.qml
+++ b/tests/quicktestbrowser/BrowserWindow.qml
@@ -505,6 +505,18 @@ ApplicationWindow {
download.accept()
}
+ MessageDialog {
+ id: notificationDialog
+ width: 200
+ standardButtons: StandardButton.Ok
+ }
+
+ function onUserNotification(notification) {
+ notificationDialog.title = notification.title
+ notificationDialog.text = notification.origin.toString() + '\n' + notification.message
+ notificationDialog.open()
+ }
+
ZoomController {
id: zoomController
y: parent.mapFromItem(currentWebView, 0 , 0).y - 4
diff --git a/tests/quicktestbrowser/FeaturePermissionBar.qml b/tests/quicktestbrowser/FeaturePermissionBar.qml
index 9c0b25966..500d13206 100644
--- a/tests/quicktestbrowser/FeaturePermissionBar.qml
+++ b/tests/quicktestbrowser/FeaturePermissionBar.qml
@@ -40,10 +40,24 @@ Rectangle {
visible: false
height: acceptButton.height + 4
- onRequestedFeatureChanged: {
- message.text = securityOrigin + " wants to access " + message.textForFeature(requestedFeature);
+
+ function textForFeature(feature) {
+ switch (feature) {
+ case WebEngineView.Geolocation: return 'Allow %1 to access your location information?'
+ case WebEngineView.MediaAudioCapture: return 'Allow %1 to access your microphone?'
+ case WebEngineView.MediaVideoCapture: return 'Allow %1 to access your webcam?'
+ case WebEngineView.MediaAudioVideoCapture: return 'Allow %1 to access your microphone and webcam?'
+ case WebEngineView.DesktopVideoCapture: return 'Allow %1 to capture video of your desktop?'
+ case WebEngineView.DesktopAudioVideoCapture: return 'Allow %1 to capture audio and video of your desktop?'
+ case WebEngineView.Notifications: return 'Allow %1 to show notification on your desktop?'
+ default: break
+ }
+ return 'Grant permission for %1 to unknown or unsupported feature [' + feature + ']?'
}
+ onRequestedFeatureChanged: {
+ message.text = textForFeature(requestedFeature).arg(securityOrigin);
+ }
RowLayout {
anchors {
@@ -54,17 +68,6 @@ Rectangle {
Label {
id: message
Layout.fillWidth: true
-
- function textForFeature(feature) {
- if (feature === WebEngineView.MediaAudioCapture)
- return "your microphone"
- if (feature === WebEngineView.MediaVideoCapture)
- return "your camera"
- if (feature === WebEngineView.MediaAudioVideoCapture)
- return "your camera and microphone"
- if (feature === WebEngineView.Geolocation)
- return "your position"
- }
}
Button {